C:正确释放multidimensional array的内存

假设您有以下ANSI C代码来初始化multidimensional array:

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

使用**a ,如何正确地将其从内存中释放?


[更新] (解决scheme)

感谢Tim(和其他人)的回答 ,我现在可以做这样一个function,从我的multidimensional array中释放内存:

 void freeArray(int **a, int m) { int i; for (i = 0; i < m; ++i) { free(a[i]); } free(a); } 

好的,有一个混乱的解释,确切地说明必要的free()调用必须在什么顺序,所以我会试图澄清人们试图得到什么,为什么。

从基本开始,释放已经使用malloc()分配的malloc() ,只需使用malloc()给出的指针就可以调用free() malloc() 。 所以对于这个代码:

 int **a = malloc(m * sizeof(int *)); 

你需要一个匹配:

 free(a); 

并为此行:

 a[i]=malloc(n * sizeof(int)); 

你需要一个匹配:

 free(a[i]); 

在类似的循环内。

如果这变得复杂的话,这是需要发生的顺序。 如果你多次调用malloc()来得到几个不同的内存块,一般来说,当你完成它们的时候,你调用free()顺序并不重要。 但是,这里的顺序非常重要,原因很简单:使用一块malloc ed内存来保存指向其他malloc内存块的指针。 因为一旦你用free()把它交回来,你 不能试图读写内存,这意味着你释放a chunk 之前 ,你将不得不释放它们存储在a[i]的指针。 存储在a[i]中的指针单独的块不依赖于彼此,因此可以按照您喜欢的顺序freeselect。

所以,把这一切放在一起,我们得到这个:

 for (i = 0; i < m; i++) { free(a[i]); } free(a); 

最后一个提示:当调用malloc() ,考虑改变这些:

 int **a = malloc(m * sizeof(int *)); a[i]=malloc(n * sizeof(int)); 

至:

 int **a = malloc(m * sizeof(*a)); a[i]=malloc(n * sizeof(*(a[i]))); 

这是干什么的? 编译器知道a是一个int ** ,所以它可以确定sizeof(*a)sizeof(int *) 。 然而,如果你以后改变了想法,并且希望char或者short或者long或者你的数组中的任何内容而不是int ,或者改写这些代码以备后用,就必须改变剩下的那个在上面第一个引用的行中引用int ,其他所有内容都将自动适用于您。 这消除了将来未被忽视的错误的可能性。

祝你好运!

撤消确切的分配:

  for (i = 0; i < m; i++) { free(a[i]); } free(a); 

请注意,您必须按照最初分配内存的相反顺序执行此操作。 如果你先free(a) ,那么a[i]在被释放之后就会访问内存,这是未定义的行为。

您需要再次迭代数组并为指向的内存执行与malloc一样多的释放,然后释放指针数组。

 for (i = 0; i < m; i++) { free (a[i]); } free (a); 

用正好相反的顺序写出你的configuration操作符,改变函数名,你就没事了。

  //Free the arrays for (i = m-1; i >= 0; i--) { free(a[i]); } free(a); 

当然,你不必相同的相反顺序释放。 你只需要跟踪一次释放相同的内存,而不是“忘记”指向分配的内存的指针(就像你先释放内存一样)。 但是以相反的顺序释放是解决后者的好办法。

正如在评论中指出的那样 ,如果分配/释放有副作用(比如C ++中的new / delete操作符),有时候释放的反向顺序比这个例子更重要。

我只会调用一次malloc()和free():

 #include <stdlib.h> #include <stdio.h> int main(void){ int i, m = 5, n = 20; int **a = malloc( m*(sizeof(int*) + n*sizeof(int)) ); //Initialize the arrays for( a[0]=(int*)a+m, i=1; i<m; i++ ) a[i]=a[i-1]+n; //...do something with arrays //How do I free the **a ? free(a); return 0; }