C:正确释放多维数组的内存
假设您有以下用于初始化多维数组的ANSI C代码:C:正确释放多维数组的内存,c,memory-management,memory-leaks,free,malloc,C,Memory Management,Memory Leaks,Free,Malloc,假设您有以下用于初始化多维数组的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
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;
}
您需要再次迭代数组,并为指向内存释放尽可能多的malloc,然后释放指针数组
for (i = 0; i < m; i++) {
free (a[i]);
}
free (a);
(i=0;i
自由(a[i]);
}
免费(a);
完全撤销您分配的内容:
for (i = 0; i < m; i++) {
free(a[i]);
}
free(a);
(i=0;i
自由(a[i]);
}
免费(a);
请注意,必须按照与最初分配内存的顺序相反的顺序执行此操作。如果您先释放了(a),那么
a[i]
将在释放后访问内存,这是一种未定义的行为。以完全相反的顺序编写分配运算符,更改函数名,您就会没事了
//Free the arrays
for (i = m-1; i >= 0; i--) {
free(a[i]);
}
free(a);
当然,您不必按完全相同的相反顺序取消分配。您只需跟踪一次完全释放相同内存的情况,并且不要“忘记”指向已分配内存的指针(就像您首先释放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;
}
#包括
#包括
内部主(空){
int i,m=5,n=20;
int**a=malloc(m*(sizeof(int*)+n*sizeof(int));
//初始化数组
对于(a[0]=(int*)a+m,i=1;i好的,有相当多的混淆来解释顺序
必需的free()
调用必须在中,因此我将尝试澄清是什么
人们都在试图达到目的,为什么
从基础开始,释放已分配的内存
使用malloc()
,只需准确地用指针调用free()
这是由malloc()
给出的。因此对于这段代码:
int **a = malloc(m * sizeof(int *));
您需要一个匹配的:
free(a);
free(a[i]);
对于这一行:
a[i]=malloc(n * sizeof(int));
您需要一个匹配的:
free(a);
free(a[i]);
在一个类似的循环中
这变得复杂的是需要发生的顺序。如果
您多次调用malloc()
,以获取不同的数据块
内存,一般来说,无论何时调用free()
的顺序是什么
你已经完成了。但是,对于一个非常重要的国家来说,订单是很重要的
具体原因:您正在使用一块malloc
ed内存来保存
指向其他malloc
ed内存块的指针。因为您必须
一旦您将内存返回,请不要尝试读取或写入内存
free()
,这意味着您必须使用
在释放a
块本身之前,它们的指针存储在a[i]
中。
包含存储在a[i]
中的指针的各个块不依赖于每个块
其他,因此可以按您喜欢的顺序免费
所以,把这些放在一起,我们得到:
for (i = 0; i < m; i++) {
free(a[i]);
}
free(a);
致:
这是做什么的?编译器知道a
是int**
,所以它可以
确定sizeof(*a)
与sizeof(int*)
相同
后来你改变主意,想要char
s或short
s或long
s或
数组中的任何内容,而不是int
s,或者修改此代码以供以后使用
用在别的东西上,你只需要改变剩下的一个
参考上文第一行中引用的int
,以及其他所有内容
将自动为您设置。这将消除这种可能性
未来未被注意到的错误
祝你好运!为什么你必须颠倒循环中的顺序?因为[1]是在[0]之后分配的,所以你应该先取消分配[1]。为什么你需要在[0]之前释放[1]呢?它们是不同的malloced块,它们之间没有依赖关系,因为free
在C中没有副作用(关于你自己的程序代码),这似乎没什么大不了的,“倒过来做”规则对于附加了<>代码>免费和 AlcOc>代码>的C++语言更为重要,就像C++中的析构函数/构造函数一样。我敢肯定大多数人会释放数组,而不是向后。说你必须以相反顺序释放可能是误导性的。你只需要释放指针数组。这不是另一种说法吗?我认为@Andomar的意思是,释放a[I]的顺序无关紧要,只是在释放a之前,你必须释放所有的a[I]。换句话说,你可以释放a[0]到a[m-1]或a[m-1]到a[0]甚至a[]但我也肯定@GregH并不意味着你必须按相反的顺序做a[],特别是考虑到他的代码。这是对问题的回答吗?Pavel Shved写了正确的答案。我只是写了一条带有代码的评论。你应该在问题的“评论”中写评论字段。它还支持代码块。@litb:请将我的答案复制到问题的注释字段中。谢谢。没有理由投反对票。我发现许多问题的答案是“你不应该那样做,改为这样做”。问题的字母和问题的含义还有回答的余地。+1回答得很好;感谢你解释了“倒序”的问题,以及做sizeof(*a)
的要点。此外,如果我错了,请纠正我,但我说sizeof(*a[I])是否正确
相当于您的sizeof(*(a[i])
,因为数组符号[]
的优先级高于*
?不,我认为您是对的。但是,我的经验法则是,如果我必须查找它,可能其他阅读我代码的人也必须查找它,以便节省时间
int **a = malloc(m * sizeof(*a));
a[i]=malloc(n * sizeof(*(a[i])));