假设您有以下用于初始化多维数组的ANSI C代码:
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
后,如何正确地从内存中释放它?
[更新] (解决方案)
感谢Tim(和其他人)answer,我现在可以做这样的功能来释放我的多维数组中的内存:
void freeArray(int **a, int m) {
int i;
for (i = 0; i < m; ++i) {
free(a[i]);
}
free(a);
}
答案 0 :(得分:65)
free()
调用,因此我将尝试澄清什么
人们正试图了解和原因。
从基础知识开始,释放已分配的内存
使用malloc()
,您只需使用指针调用free()
即可
由malloc()
给出的。所以对于这段代码:
int **a = malloc(m * sizeof(int *));
你需要匹配:
free(a);
并为此行:
a[i]=malloc(n * sizeof(int));
你需要匹配:
free(a[i]);
在类似的循环中。
这变得复杂的是这需要发生的顺序。如果
你多次打malloc()
来获得几个不同的块
记忆,一般来说,当你调用free()
的顺序并不重要
你已经完成了他们。但是,订单在这里非常重要
具体原因:您正在使用一块malloc
个内存来保存
指向malloc
内存的其他块的指针。因为必须
一旦您将内存交回,不会尝试读取或写入内存
free()
,这意味着你将不得不释放这些块
他们的指针存储在a[i]
之前你释放a
块本身。
存储在a[i]
中的指针的各个块不依赖于每个块
其他,所以可以free
d,无论你喜欢哪种顺序。
所以,把这一切放在一起,我们得到了这个:
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
,以及其他所有内容
会自动落到你的位置。这消除了可能性
未来的未被注意的错误。
答案 1 :(得分:8)
完全撤消您分配的内容:
for (i = 0; i < m; i++) {
free(a[i]);
}
free(a);
请注意,您必须按照最初分配内存的 reverse 顺序执行此操作。如果你先做free(a)
,那么a[i]
将在释放后访问内存,这是未定义的行为。
答案 2 :(得分:4)
你需要再次迭代数组,并为指向内存的malloc执行尽可能多的释放,然后释放指针数组。
for (i = 0; i < m; i++) {
free (a[i]);
}
free (a);
答案 3 :(得分:3)
以完全相反的顺序编写您的分配运算符,更改函数名称,您就可以了。
//Free the arrays
for (i = m-1; i >= 0; i--) {
free(a[i]);
}
free(a);
当然,您不必以相同的反转顺序解除分配。你只需要跟踪一次释放相同的内存,而不是“忘记”分配内存的指针(就像你首先释放a
一样)。但是以相反的顺序解除分配是拇指很好地解决后者的问题。
正如评论中litb所指出的那样,如果分配/解除分配有副作用(如C ++中的new
/ delete
运算符),有时重新分配的后向顺序会更多比这个特定的例子重要。
答案 4 :(得分:1)
我只会调用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;
}