And*_*ech 38 c malloc free memory-leaks memory-management
假设您有以下用于初始化多维数组的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;
}
Run Code Online (Sandbox Code Playgroud)
使用后**a
,如何正确地从内存中释放它?
[更新](解决方案)
感谢Tim(以及其他人)的回答,我现在可以做这样的功能来从我的多维数组中释放内存:
void freeArray(int **a, int m) {
int i;
for (i = 0; i < m; ++i) {
free(a[i]);
}
free(a);
}
Run Code Online (Sandbox Code Playgroud)
Tim*_*Tim 67
好吧,有一个很大的混乱,解释了必要的free()
呼叫必须在什么顺序,所以我会试着澄清人们想要得到什么以及为什么.
从基础知识开始,为了释放已经分配的内存malloc()
,您只需free()
使用您给出的指针进行调用即可malloc()
.所以对于这段代码:
int **a = malloc(m * sizeof(int *));
Run Code Online (Sandbox Code Playgroud)
你需要匹配:
free(a);
Run Code Online (Sandbox Code Playgroud)
对于这一行:
a[i]=malloc(n * sizeof(int));
Run Code Online (Sandbox Code Playgroud)
你需要匹配:
free(a[i]);
Run Code Online (Sandbox Code Playgroud)
在一个类似的循环内.
这变得复杂的是这需要发生的顺序.如果你malloc()
多次打电话来获得几个不同的内存块,一般来说,free()
当你完成它们时,你调用的顺序并不重要.但是,顺序在这里非常重要,原因很简单:您正在使用一块malloc
内存来保存指向其他malloc
内存块的指针.因为一旦你把它移回来就
不能尝试读取或写入内存
free()
,这意味着你必须a[i]
在你释放a
块本身之前释放存储在其中的指针.存储指针的各个块a[i]
不相互依赖,因此可以free
按照您喜欢的顺序排列.
所以,把这一切放在一起,我们得到这个:
for (i = 0; i < m; i++) {
free(a[i]);
}
free(a);
Run Code Online (Sandbox Code Playgroud)
最后一个提示:打电话时malloc()
,请考虑更改这些:
int **a = malloc(m * sizeof(int *));
a[i]=malloc(n * sizeof(int));
Run Code Online (Sandbox Code Playgroud)
至:
int **a = malloc(m * sizeof(*a));
a[i]=malloc(n * sizeof(*(a[i])));
Run Code Online (Sandbox Code Playgroud)
这是做什么的?编译器知道它a
是一个int **
,所以它可以确定它sizeof(*a)
是相同的sizeof(int *)
.但是,如果您稍后改变主意并希望在数组中使用char
s或short
s或long
s或其他内容而不是int
s,或者您调整此代码以便以后在其他内容中使用,则必须更改其中的一个剩余引用int
.首先引用上面一行,其他一切将自动落到你的位置.这消除了将来未被注意的错误的可能性.
祝好运!
完全撤消您分配的内容:
for (i = 0; i < m; i++) {
free(a[i]);
}
free(a);
Run Code Online (Sandbox Code Playgroud)
请注意,必须按照最初分配内存的相反顺序执行此操作.如果你先做了free(a)
,那么a[i]
在它被释放后将访问内存,这是未定义的行为.