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]
中的指针单独的块不依赖于彼此,因此可以按照您喜欢的顺序free
select。
所以,把这一切放在一起,我们得到这个:
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; }