2010-12-04 2 views
0

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

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».

ответ

2

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

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() S: part1, part2 и как куски памяти, к которой one заостренные. Поскольку вы перезаписываете первый one, вы потеряли этот указатель и не можете напрямую указать free().К счастью, вы сохранили этот указатель в part1[0] и можете использовать его для free() всей указанной памяти.

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

1

У вас есть только 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); 
+0

Это была моя первая попытка, но она давала мне утечки памяти (т. Е. Через несколько часов повторного цикла, она занимала более 10 ГБ памяти, что слишком велико, когда nx всего 16). – wolfPack88 2010-12-04 19:05:29

+1

@ wolfPack88: Вы рассмотрели возможную утечку, о которой я упоминал выше, т. Е. У вас есть отдельные два отдельных блока «один» и освободить их обоих? – casablanca 2010-12-04 19:07:16

1

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

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

... (Other code here) 
/* four mallocs so four frees */ 
free(part1[0]); 
free(part2[0]); 
free(part1); 
free(part2); 
Смежные вопросы