#c #arrays #free
#c #массивы #Бесплатно
Вопрос:
У меня есть struct cell
->
struct cell {
double x, y, h, g, rhs;
struct key *keys;
};
И я использую следующий метод для освобождения ячейки ->
void cellFree(struct cell *c) {
// Free the keys
free(c->keys);
// Free the cell itself.
free(c);
}
void cellFreeSors(struct cell *cn) {
int i;
for(i = 0; i < 5; i ) {
// Free keys
free(cn[i].keys);
}
// Free array
free(cn);
}
Теперь я столкнулся со странной проблемой с одним из созданных мной массивов malloc’d.
В принципе, я пытаюсь найти соседей ячейки и выполняю некоторую обработку на основе их значений, используя следующие два метода ->
struct cell * cellGetSuccessors(struct cell *c, struct cell *sstart, struct cell *sgoal, double km) {
int i;
// CREATE 5 CELLS
struct cell *cn = malloc(5 * sizeof (struct cell));
if (cn == NULL) {
printf("--> Unable to malloc *cn!n");
errno = ENOMEM;
return NULL;
}
for(i = 0; i < 5; i ) {
cn[i].keys = malloc(sizeof(struct key));
if (cn[i].keys == NULL) {
printf("--> Unable to malloc *cn[%d].keys!n", i);
errno = ENOMEM;
return NULL;
}
cellCopyValues(amp;cn[i], c);
}
// MAKE THEM NEIGHBORS
// PROCESS
return cn;
}
double cellRHS(struct cell *c, struct cell *sstart, struct cell *sgoal, double km, struct cell * prevCell) {
// GET NEIGHBORS of c
struct cell *cn = cellGetSuccessors(c, sstart, sgoal, km);
double minsum;
// SOME PROCESS TO UPDATE minsum
minsum = 5.232111; // SAY
// Free memory
cellFreeSors(cn);
return minsum;
}
Проблема в том, что когда я вызываю cellFreeSors()
in cellRHS()
, я сталкиваюсь с проблемами позже..
Вот как вызываются эти функции..
struct cell *u = cellCreateNew();
u->rhs = cellRHS(u, sstart, sgoal, km, prevCell);
queueAdd(amp;U, u);
Это приводит к ошибке сегментации при попытке распечатать мою очередь ->
QUEUE CONTENTS
==================================================================
F -> 0x2354550
L - >0x2354550
(1) [0x2354550] X 50.000000, Y 45.000000 PREV: (nil) NEXT: 0x4014000000000000
Segmentation fault
Как вы можете видеть, СЛЕДУЮЩАЯ запись, похоже, по какой-то причине инициализирована.
Тот же код при выполнении БЕЗ cellRHS()
работает нормально .. ->
struct cell *u = cellCreateNew();
queueAdd(amp;U, u);
QUEUE CONTENTS
==================================================================
F -> 0x2354550
L - >0x2354550
(1) [0x2354550] X 50.000000, Y 45.000000 PREV: (nil) NEXT: (nil)
Почему cellFreeSors()
возникает эта проблема? Мне не нужны созданные соседи u за пределами cellRHS
. Что я делаю не так?
Спасибо..
** РЕДАКТИРУЕТ структуру для queue_node следующим образом
/* QUEUE NODE
* ----------------------------
* Contains a struct cell c and
* reference to next queue_node
*/
struct queue_node {
struct cell *c;
struct queue_node *next;
struct queue_node *prev;
};
/* PRIORITY QUEUE
* ----------------------------
* The queue itself, with first
* and last pointers to queue_nodes
*/
struct priority_queue {
struct queue_node *first;
struct queue_node *last;
};
queuePrint()
Метод показывает содержимое очереди ->
void queuePrint(struct priority_queue *q)
{
printf("nntQUEUE CONTENTSnt==================================================================n");
int i = 1;
struct queue_node *temp = q->first;
printf("tF -> %pntL -> %pn", q->first, q->last);
while(temp != NULL) {
printf("t(%d) [%p]tX %f, Y %ftPREV: %ptNEXT: %p", i, temp, temp->c->x, temp->c->y, temp->prev, temp->next);
printf("n");
temp = temp->next;
i ;
}
printf("nn");
}
Комментарии:
1. Нет необходимости настраивать
ENOMEM
самостоятельно;malloc
сделает это за вас. На самом деле, это может скрывать другие ошибки. ЧтоcellCopyValues
делает?2. Я не вижу указателя prev или next в вашей структуре. И вы не включили код, который нарушает сегментацию (я предполагаю, что это в queueAdd или что-то еще, отображающее содержимое очереди).
3. не забывайте о вопросе Ларсмана на
cellCopyValues
, плюс он точен в том, что касаетсяerrno
, вам не следует его менять.4. Вы инициализируете указатели
prev
иnext
при создании записи очереди? Код дляqueueAdd()
может помочь. Но, когда вы создаете новый элемент очереди, инициализируйте его перед добавлением в очередь.
Ответ №1:
Несколько предложений здесь:
-
Используйте централизованный метод allocCell() и FreeCell(). Это позволяет точно отслеживать каждую выделенную и освобожденную ячейку.
-
Поместите идентификатор в каждую ячейку. Опять же, это позволяет выполнять детальную трассировку. Вы можете скомпилировать его одним способом для производства и другим для отладки, если возникает проблема с пространством.
-
Напишите процедуры трассировки для ячейки, чтобы убедиться, что ваши процедуры освобождают только выделенные ячейки, что любая ячейка освобождается только один раз и т.д. Вы могли бы даже написать хэш-таблицу для хранения идентификаторов выделенных и освобожденных ячеек (конечно, только во время отладки) и написания проверочных проверок.
-
Вероятно, вы снова столкнетесь с ошибками памяти, если не сделаете этого.
-
Даже если вы сделаете это, вы снова столкнетесь с ошибками памяти, но эти инструменты помогут вам быстрее отследить это в следующий раз.
-
Переключитесь на C # или java и ничего не освобождайте 🙂