C: Освобождение массива malloc в неподходящее время? - PullRequest
2 голосов
/ 14 апреля 2011

У меня есть 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. По сути, я пытаюсь найти соседей ячейки и выполняю некоторую обработку на основе их значений, используя следующие два метода ->

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(&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() в cellRHS(), я сталкиваюсь с проблемами позже .. Так называются эти функции ..

struct cell *u = cellCreateNew();
u->rhs = cellRHS(u, sstart, sgoal, km, prevCell);
queueAdd(&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(&U, u);

    QUEUE CONTENTS
    ==================================================================
    F -> 0x2354550
    L - >0x2354550
    (1) [0x2354550] X 50.000000, Y 45.000000    PREV: (nil) NEXT: (nil)

Почему cellFreeSors() вызывает эту проблему? Я не использую порожденных вами соседей, выходящих за рамки 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("\n\n\tQUEUE CONTENTS\n\t==================================================================\n");
    int i = 1;
    struct queue_node *temp = q->first;
    printf("\tF -> %p\n\tL -> %p\n", q->first, q->last);
    while(temp != NULL) {
        printf("\t(%d) [%p]\tX %f, Y %f\tPREV: %p\tNEXT: %p", i, temp, temp->c->x, temp->c->y, temp->prev, temp->next);
        printf("\n");
        temp = temp->next;
        i++;
    }
    printf("\n\n");
}

1 Ответ

1 голос
/ 14 апреля 2011

Некоторые предложения здесь:

  1. Используйте централизованный allocCell () и метод freeCell (). Это позволяет вам проследить каждый выделенный и освободил ячейку точно.

  2. Поставь идентификатор на каждой клетке. Опять же, это позволяет детальная трассировка. Вы можете скомпилировать это один путь для производства и другой для отладки, если пробел является проблемой.

  3. Запись процедур трассировки для ячейки, чтобы увидеть, что ваши процедуры только освободив выделенные клетки, что нибудь клетка освобождается только один раз и т. д. может даже написать хеш-таблицу хранить идентификаторы выделенных и освобожденные клетки (конечно, только во время отладка) и запись проверки чеки.

  4. Вы, вероятно, собираетесь столкнуться с ошибками памяти снова, если вы не делай этого.

  5. Даже если вы сделаете это, вы снова столкнетесь с ошибками памяти, но эти инструменты помогут вам быстрее отследить их в следующий раз.

  6. Переключитесь на C # или Java и ничего не освобождайте:)

...