C утечка памяти, несмотря на свободный - PullRequest
10 голосов
/ 08 февраля 2011

При отладке моей программы с помощью Valgrind я обнаружил утечку памяти, несмотря на то, что я считал эффективными вызовами free. Во-первых, код, который выделяет память и хранит ее:

    row = malloc(sizeof(Row));
    row->columns = malloc(sizeof(char*) * headcnt);
    row->numcol  = 0;

    ...

    row->numcol    = colcnt;
    rows           = realloc(rows, (rowcnt+1) * sizeof(Row));
    rows[rowcnt++] = *row;

Код, ответственный за попытку освободить память:

void cleanUp(){
    int i = 0;
    int j = 0;

    for (i = 0; i < rowcnt; i++){
        for (j = 0; j < rows[i].numcols; j++){
            free(rows[i].columns[j]);
        }
        free(&rows[i]);
    }
    free(rows); 
    exit(0);
}

Объявление строки:

typedef struct {
    char** columns;
    unsigned short int numcol;
} Row;

Row* rows = NULL;

Хуже того, эта программа иногда вызывает ошибку glibc на free(&rows[i]), которая жалуется на двойное освобождение. Я новичок в C, и был бы признателен за любые указатели (хм) кто-то может иметь.

Ответы [ 3 ]

8 голосов
/ 08 февраля 2011

Выполнение rows[rowcnt++] = *row; эффективно создает копию выделенной памяти. Строки вашего массива должны быть массивом указателей. Также, как отметил Оли Чейлсворт, вы должны бесплатно платить за столбцы, а за все столбцы - один бесплатный.

rows = malloc(count * sizeof(Row*)); // This is probably done somewhere

row->columns = malloc(sizeof(char*) * headcnt);
row->numcol  = 0;

...

row->numcol    = colcnt;
rows           = realloc(rows, (rowcnt+1) * sizeof(Row*));
rows[rowcnt++] = row;

Теперь, если ваша уборка

void cleanUp(){
    int i = 0;
    int j = 0;

    for (i = 0; i < rowcnt; i++){
        free(rows[i]->columns);
    }
    free(rows); 
    exit(0);
}
5 голосов
/ 08 февраля 2011

Каждый вызов malloc (или realloc) должен соответствовать соответствующему вызову free.Если вы динамически распределяете массив таким образом:

int *p = malloc(sizeof(int) * NUM);

Вы освобождаете его так:

free(p);

Не так:

for (int i = 0; i < NUM; i++)
{
    free(p[i]);
}

Похоже,делает это неправильно.Я подозреваю , что ваш код очистки должен быть:

void cleanUp(){
    int i = 0;
    int j = 0;

    for (i = 0; i < rowcnt; i++){
        for (j = 0; j < rows[i].numcols; j++){
            free(rows[i].columns[j]); // Free whatever rows[i].columns[j] points to
        }
        free(rows[i].columns); // Matches row->columns = malloc(sizeof(char*) * headcnt);
    }
    free(rows);  // Matches rows = realloc(rows, (rowcnt+1) * sizeof(Row));
    exit(0);
}

Кроме того, нет способа сопоставить row = malloc(sizeof(Row));подозреваю , что ваш код распределения должен быть:

row->numcol    = colcnt;
rows           = realloc(rows, (rowcnt+1) * sizeof(Row));
rows[rowcnt].columns = malloc(sizeof(char*) * headcnt);
rows[rowcnt].numcol = 0;
rowcnt++;
0 голосов
/ 08 февраля 2011

Может быть, я плотный, но разве это совершенно не нужно?В любом случае, вся ваша память будет освобождена при выходе из программы.

...