C: Correctement la libération de la mémoire d'un tableau multidimensionnel
Dire, vous avez le C ANSI code qui initialise un tableau multidimensionnel :
int main()
{
int i, m = 5, n = 20;
int **a = malloc(m * sizeof(int *));
//Initialize the arrays
for (i = 0; i < m; i++) {
a[i]=malloc(n * sizeof(int));
}
//...do something with arrays
//How do I free the **a ?
return 0;
}
Après l'utilisation de la **a
, comment puis-je libérer correctement à partir de la mémoire ?
[Mise À Jour] (Solution)
Grâce à Tim (et les autres) réponse, je peux maintenant faire une telle fonction pour libérer de la mémoire de mon tableau multidimensionnel :
void freeArray(int **a, int m) {
int i;
for (i = 0; i < m; ++i) {
free(a[i]);
}
free(a);
}
- La terminologie chipoter: ce n'est pas ce que C appelle généralement un "tableau multidimensionnel". C'est juste le seul moyen d'utiliser la syntaxe
a[i][j]
, tout en permettant à la fois des dimensions inconnues au moment de la compilation. L'autre type de tableau multidimensionnel à un tableau de tableaux, à la place de ce tableau de pointeurs (les premiers éléments de l') des tableaux.
Vous devez vous connecter pour publier un commentaire.
OK, il y a juste beaucoup de confusion en expliquant exactement ce que l'ordre de la
nécessaire
free()
les appels doivent être en, donc je vais essayer de clarifier ce que l'les gens essaient de l'obtenir et pourquoi.
En commençant par les bases, pour libérer de la mémoire qui a été allouée
à l'aide de
malloc()
, il vous suffit d'appelerfree()
avec exactement le pointeurqui vous ont été donnés par
malloc()
. Donc, pour ce code:vous avez besoin d'un correspondant:
et pour cette ligne:
vous avez besoin d'un correspondant:
à l'intérieur d'un semblable boucle.
Où cela devient compliqué, c'est de l'ordre de ce qui doit arriver. Si
vous appelez
malloc()
, à plusieurs reprises, plusieurs morceaux dede mémoire, en général, il n'a pas d'importance quel ordre vous appelez
free()
quandvous avez fait avec eux. Cependant, l'ordre est important pour un très
raison: à l'aide d'un morceau de
malloc
ed de mémoire pour contenirles pointeurs vers d'autres morceaux de
malloc
ed mémoire. Parce que vous doitpas tentative de lecture ou d'écriture de la mémoire une fois que vous avez remis de retour avec
free()
, cela signifie que vous allez avoir à libérer les morceaux avecleurs pointeurs stockés dans
a[i]
avant vous libérer de l'a
morceau lui-même.Les morceaux individuels avec les pointeurs stockés dans
a[i]
ne sont pas dépendants les uns desd'autres, et peut donc être
free
d dans n'importe quel ordre que vous voulez.Afin de, mettre tous ensemble, nous obtenons ceci:
Un dernier conseil: lors de l'appel
malloc()
, envisager de modifier ces:à:
Qu'est-ce à faire? Le compilateur sait que
a
est unint **
, de sorte qu'il peutdéterminer que
sizeof(*a)
est le même quesizeof(int *)
. Toutefois, siplus tard, vous changez d'avis et souhaitez
char
s oushort
s oulong
s ouque ce soit dans votre tableau au lieu de
int
s, ou vous adapter ce code pour plus tardl'utilisation à quelque chose d'autre, vous aurez à changer juste le reste
référence à
int
dans le premier cité de la ligne ci-dessus, et tout le resteva automatiquement se mettre en place pour vous. Cela supprime la probabilité
de inaperçus des erreurs dans l'avenir.
Bonne chance!
sizeof(*a)
sizeof(*a[i])
est équivalent à votresizeof(*(a[i]))
, depuis le tableau de notation[]
ont une priorité plus élevée que*
?Annuler exactement ce que vous avez alloué:
Notez que vous devez le faire dans les inverse commande à partir de laquelle vous avez la mémoire allouée. Si vous n'avez
free(a)
d'abord, puisa[i]
serait pour accéder mémoire après qu'il a été libéré, ce qui est un comportement indéterminé.Vous avez besoin pour effectuer une itération de nouveau le tableau et de faire comme de nombreuses libère comme mallocs pour le fait de la mémoire, puis libérer le tableau de pointeurs.
Écrire votre allocation des opérateurs exactement dans l'ordre inverse, en changeant les noms de fonctions, et vous serez bien.
Bien sûr, vous n'avez pas ont pour désallouer dans le même ordre inverse. Vous avez juste à garder la trace sur libérant de la mémoire même exactement une fois et de ne pas "oublier" des pointeurs vers la mémoire allouée (comme il l'aurait été si vous gratuit, la
a
premier). Mais la désallocation dans l'ordre inverse est une bonne rôle de pouce à l'adresse de ce dernier.Comme indiqué par litb dans les commentaires, si l'allocation/désallocation eu des effets secondaires (comme
new
/delete
opérateurs en C++), parfois à l'envers de l'ordre de la libération serait plus important que dans cet exemple particulier.free
est sans effets secondaires en C (au sujet de votre propre code de programme), il ne semble pas avoir beaucoup d'importance. "Le faire dans le sens inverse de la règle" est de plus en plus important pour les langues qui ont un effet secondaire attaché àfree
etalloc
, comme en C++ avec ses destructeurs/constructeurs.Je voudrais appeler malloc() et free() qu'une seule fois: