2010-12-04 5 views
0

Dans mon code, j'ai plusieurs pointeurs vers des pointeurs (par exemple des variables float **), et il semble que des problèmes se posent pour libérer leur mémoire afin de ne pas causer de fuites de mémoire. Voici le code que je l'ai écrit:C libérant le pointeur sur le pointeur

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); 

Ce code passe par, fait les calculs correctement, mais des erreurs dans la boucle libre. Cela fonctionne pour k = 0, mais en essayant de libérer part1 [1] et part2 [1], cela me donne l'erreur "glibc detected".

Répondre

2

Tout d'abord:

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

Ceux-ci devraient être

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

Vous souhaitez allouer un tas de float s et float * s , et non float ** s et float *** s

Deuxièmement, vous faites 4 allocations - vous allouez one, et les index dedans part1, et allouez one encore, (en oubliant l'ancienne adresse), et les indices dedans part2.

Cela signifie que vous devriez avoir 4 free() s: part1, part2, et les deux morceaux de mémoire qui one pointue. Parce que vous remplacez le premier one, vous avez perdu ce pointeur et ne pouvez pas directement free() il.Heureusement, vous avez enregistré ce pointeur dans part1[0], et vous pouvez l'utiliser pour free() toute la mémoire pointée vers. Option

Une autre (peut-être plus clair et plus idiomatiques) serait d'affecter différemment. Allouer part1, puis boucle pour allouer chaque part1[k], et la même chose pour part2.

+0

Je ne voulais pas faire ça parce que la mémoire ne serait alors pas contiguë, n'est-ce pas? Je crois que cela entraînerait une perte d'efficacité. Évidemment, travailler inefficacement vaut mieux que ne pas travailler du tout, mais j'essayais juste de faire fonctionner ça comme ça. Aussi, je sauvegarde le pointeur sur un dans plus que juste part1 [0], non? Ma première boucle enregistre le pointeur dans part1 [k] car k passe de 0 à nx, c'est pourquoi j'ai essayé de libérer la même quantité de mémoire. – wolfPack88

+1

"Ma première boucle enregistre le pointeur dans la partie 1 [k] lorsque k passe de 0 à nx". Non, vous enregistrez _offsets_ d'un. & un [0] = un. & un [k] = un + k. libre (un) libère toute la masse de la mémoire, comme le serait la liberté (partie 1 [0]); – wnoise

+0

Ah ... c'est logique. Merci pour l'aide. – wolfPack88

1

Vous avez seulement 4 malloc appels, donc vous ne devriez avoir 4 free appels. Vous n'avez jamais rien alloué en boucle, alors pourquoi libérez-vous en boucle?

part1[k] et part2[k] ont jamais été attribués par eux-mêmes, ils font juste une zone de la mémoire allouée à one, donc vous devriez juste libre one. En outre, vous avez une fuite de mémoire ici:

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); 

La raison pour laquelle votre code fonctionne pour k = 0 est parce que part1[0] == &one[0] == one, à savoir part1[0] pointe en réalité au début du bloc one - en libérant cela, vous libérez le bloc entier .

Et je ne suis pas sûr de ce que votre sizeof signifie. Je suppose que vous vouliez allouer nx * nx flotteurs - si oui, cela devrait être sizeof(*one) - *one est un flottant, mais &one est l'adresse de one, qui est un pointeur float **.


Vous voulez vraiment faire quelque chose comme ceci:

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

Ce fut ma première tentative, mais il me donnait des fuites de mémoire (à savoir, après quelques heures de boucles répétées, il a été pris au-dessus de 10 Go de mémoire, ce qui est beaucoup trop grand quand nx est seulement 16). – wolfPack88

+1

@ wolfPack88: Avez-vous considéré la fuite possible que j'ai mentionnée ci-dessus, c'est-à-dire avez-vous eu deux blocs 'one' séparés et les avez libérés tous les deux? – casablanca

+0

Je n'ai pas, mais je n'étais pas certain que cela causerait une fuite de mémoire ... Si je stocke le pointeur unique dans la partie 1, puis libre partie1, il devrait y avoir aucune fuite de mémoire, correct? Ou est-ce que je ne comprends pas la façon dont l'allocation de mémoire fonctionne? – wolfPack88

1

Regardez combien de malloc vous faites et combien vous libère faites. Les chiffres ne correspondent pas.

En général, vous ne pouvez pas libérer une partie d'une structure malloc'd. Vous pouvez seulement tout libérer. Ainsi, à la fin vous voulez quelque chose comme:

... (Other code here) 
/* four mallocs so four frees */ 
free(part1[0]); 
free(part2[0]); 
free(part1); 
free(part2);