Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/69.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C:正确释放多维数组的内存_C_Memory Management_Memory Leaks_Free_Malloc - Fatal编程技术网

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

假设您有以下用于初始化多维数组的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;
}

您需要再次迭代数组,并为指向内存释放尽可能多的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])));