你如何在C中释放2D malloc< d?数组?

时间:2016-07-01 02:25:48

标签: c free

我在C中创建一个2D数组;我正确地解放了吗?

// create
int n = 3;
int (*X)[n] = malloc(sizeof(int[n][n]));

// set to 0
for(int i = 0; i < n; i++) {
    for (int j = 0; j < n; j++) {
        X[i][j] = 0;
    }
}   

// is this all I need?
free(X);

3 个答案:

答案 0 :(得分:3)

您必须为每个free致电malloc一次。您的代码有一个malloc和一个free(具有相同的地址),所以它是正确的。

答案 1 :(得分:0)

对于每个malloc(),必须有匹配的free()。因此,如果您在循环中调用malloc(),则必须在稍后的调用free()上进行类似的循环。您的代码有一个malloc()和一个对应的free(),所以是的,您有free d所需的一切。

我见过分配二维数组最常见的方法是做类似的事情:

int **arr = malloc(sizeof (int *) * num_rows);

for (i = 0; i < num_rows; ++i)
        arr[i] = malloc(sizeof (int) * num_cols);
/*
  * Using `sizeof *arr` and `sizeof **arr`
  * respectively would have been more safe,
  * but for the purpose of this example, I think
  * using `int *` and `int` is simpler to
  * understand.
  */

然后再免费:

for (i = 0; i < num_rows; ++i)
        free(arr[i]);

free(arr);

这使得外部维度保持num_row指向指向int的指针(每个num_row指针指向&#39;列的起始地址&#39;)。因此,外部维度中的每个元素都指向一行,并且在每一行中,内部维度中有num_cols个元素(&#39;列&#39;),这只是{{1}的一组整数。你能理解这个吗?因此,您必须分配num_cols个整数指针,并将这些指针中的每一个指向第一个&#39;列。该行的每一行 - 你必须为num_rows整数分配空间,所以你可以看到循环将总共有num_cols个整数,并且它们被分配的方式允许你使用数组索引符号(在这种情况下是二维的 - 外部维度中的每个元素都指向一行&#39;行的开头,其中包含一个指向&#39;列开头的指针,因此双指针)访问元素。我知道这可能令人困惑,这就是为什么我试着用很多不同的时间/方式描述它,但请你问任何问题,特别是关于你不了解的内容,我会非常乐意与您一起帮助理解它。

我并不是说你必须以这种方式创建二维阵列;你的方式也很好,我只是想以这种方式向你展示,因为它可能会遇到它,因为它很常见。

另外,看看Valgrind。您可以使用该工具查看您是否忘记了任何num_rows * num cols /具有不匹配的free(),并告诉您是否有任何已分配的内存无法访问/泄露(可能在调用之前指针已更改)到malloc()所以呼叫没有正确释放内存而你会泄漏。)

答案 2 :(得分:0)

RastaJedi - 还有几件事要注意: 在调用 free() 之后,最好将 free'd 变量设置为 NULL,这有助于防止在 free 后使用。 此外,如果您在一个代码块中 malloc,然后在某个被调用的函数中释放,然后从该函数返回,有时 C 会忘记最终的释放(在您的示例中, free(arr) ),您应该将变量设置为返回时为 NULL。

我来到这里,并验证了我在我正在处理的代码中编写的 malloc 和 free 调用确实与您的“常见”方式完全一样,但一直遇到 Seg Fault,因为我使用的是来自在 main 中,从接收数组的双间接头的辅助函数中释放出来。将所有这些都包装在一个用于用户交互的 while 循环中,第二遍是检查数组头是否为 NULL,但没有将其视为 NULL,尽管在辅助函数内显式设置为 NULL。使用调试器遍历代码是我识别行为的方式,以及我来查找的原因。

释放后,内存可用,并以各种方式(随机)重新分配;当带有 free() 调用的函数返回时,分配的内存已被释放,但似乎调用代码仍持有指向内存中该位置的指针。然后存在可能的竞争条件;当调用代码重新获得控制权时,无法保证用于数组头的变量指向的位置,因此在函数返回后将变量设置为 NULL 是一个非常好的主意。

虽然你可以使用 malloc 的指针来传递引用行为,但在某个函数内部调用 free() 之后,引用行为会中断(因为被引用的东西是被释放的) .

所以,感谢您的回答,这证实了我在看问题的错误部分 - 只是想也许其他人可能会在这里绊倒,并且可能遇到与我相同的问题。