C освобождает указатель на указатель - PullRequest
0 голосов
/ 04 декабря 2010

В моем коде у меня есть несколько указателей на указатели (например, переменные типа float **), и у меня, похоже, возникают проблемы с освобождением их памяти, чтобы не вызвать утечек памяти. Вот код, который я написал:

float *one, **part1, **part2;

one = malloc(sizeof(&one) * nx * nx);
part1 = malloc(sizeof(&part1) * nx);

if(one == NULL || part1 == NULL) {
 printf("Memory error.\n");
 exit(2);
}

for(k = 0; k < nx; k++)
 part1[k] = &one[k * nx];

one = malloc(sizeof(&one) * nx * nx);
part2 = malloc(sizeof(&part2) * nx);

if(one == NULL || part2 == NULL) {
 printf("Memory error.\n");
 exit(2);
}

for(k = 0; k < nx; k++)
 part2[k] = &one[k * nx];

... (Other code here)

for(k = 0; k < nx; k++) {
 free(part1[k]);
 free(part2[k]);
}

free(one);
free(part1);
free(part2);

Этот код выполняется, правильно выполняет вычисления, но затем выдает ошибки в свободном цикле. Он работает для k = 0, но затем при попытке освободить part1 [1] и part2 [1] выдает ошибку «обнаружен glibc».

Ответы [ 3 ]

2 голосов
/ 04 декабря 2010

Прежде всего:

one = malloc(sizeof(&one) * nx * nx);
part1 = malloc(sizeof(&part1) * nx);

Это должно быть

one = malloc(sizeof(*one) * nx * nx);
part1 = malloc(sizeof(*part1) * nx);

Вы хотите выделить группу float с и float * с, а не float ** с и float *** с

Во-вторых, вы делаете 4 выделения - вы выделяете one и индексы в него в part1, и снова выделите one (забыв старый адрес) и указав в нем индексы в part2.

Это означает, что у вас должно быть 4 free() с: part1, part2 и оба блока памяти, на которые указывал one. Поскольку вы перезаписали первый one, вы потеряли этот указатель и не можете напрямую free() его. К счастью, вы сохранили этот указатель в part1[0] и можете использовать его для free() всей памяти, на которую указывает.

Другой (возможно, более четкий и более идиоматический) вариант - распределять по-другому. Выделите part1, а затем выполните цикл для выделения каждого part1[k], и то же самое для part2.

1 голос
/ 04 декабря 2010

Посмотрите, сколько malloc вы делаете, и сколько освобождений вы делаете. Номера не совпадают.

Как правило, вы не можете освободить часть структуры malloc'd. Вы можете только освободить все это. Итак, в конце вы хотите что-то еще, как:

... (Other code here)
/* four mallocs so four frees */
free(part1[0]);
free(part2[0]);
free(part1);
free(part2);
1 голос
/ 04 декабря 2010

У вас есть только 4 malloc звонки, поэтому вы должны иметь только 4 free звонки.Вы никогда ничего не выделяли в цикле, так почему вы освобождаете в цикле?

part1[k] и part2[k] никогда не выделялись сами по себе, они просто указывают на область памяти, выделенную для one, так что вы должны просто бесплатно one.Кроме того, здесь есть утечка памяти:

one = malloc(sizeof(&one) * nx * nx);
part1 = malloc(sizeof(&part1) * nx);

...

// *** You just lost the previous old pointer here *** //
one = malloc(sizeof(&one) * nx * nx);
part2 = malloc(sizeof(&part2) * nx);

Причина, по которой ваш код работает для k = 0, заключается в том, что part1[0] == &one[0] == one, то есть part1[0] фактически указывает на начало блока one -освобождая это, вы освобождаете весь блок.

И я не уверен, что означает ваш sizeof.Я предполагаю, что вы хотели выделить nx * nx с плавающей точкой - если это так, это должно быть sizeof(*one) - *one это число с плавающей точкой, но &one это адрес one, то есть float **указатель.


Вы действительно хотите сделать что-то вроде этого:

one1 = malloc(sizeof(*one) * nx * nx);
part1 = malloc(sizeof(*part1) * nx);

...

for(k = 0; k < nx; k++)
 part1[k] = &one1[k * nx];

...

free(part1);
free(one1);
...