C:正确释放多维数组的内存

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 *).但是,如果您稍后改变主意并希望在数组中使用chars或shorts或longs或其他内容而不是ints,或者您调整此代码以便以后在其他内容中使用,则必须更改其中的一个剩余引用int.首先引用上面一行,其他一切将自动落到你的位置.这消除了将来未被注意的错误的可能性.

祝好运!

  • +1优秀的答案; 感谢您解释关于逆序的问题,以及关于做`sizeof(*a)`的观点 (2认同)

Gre*_*ill 8

完全撤消您分配的内容:

  for (i = 0; i < m; i++) { 
      free(a[i]);
  }
  free(a);
Run Code Online (Sandbox Code Playgroud)

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

  • 说你必须以相反的顺序释放可能会产生误导.你只需要在指针之后释放指针数组. (2认同)
  • 我认为@Andomar意味着你释放a [i]的顺序并不重要,只是你必须在释放之前释放所有这些.换句话说,你可以通过[0]通过[0]通过[m-1]或[m-1]或通过所有偶数[]来释放[],然后是赔率.但我也确定@GregH并不意味着*你必须以相反的顺序执行a [],特别是考虑到他的代码. (2认同)