你如何在 C 中释放一个 2D malloc'd 数组?
How do you free a 2D malloc'd array in C?
我正在用 C 语言创建一个二维数组;我是否正确释放它?
// 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);
对于每个 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
指针都指向 'column' 的起始地址)。所以外部维度中的每个元素指向一行,而在每一行中,内部维度('columns')中有num_cols
个元素,这只是一组num_cols
个整数。你能理解这个吗?因此,您必须分配 num_rows
个整数指针,并且每个指针都指向该行的第一个 'column'——对于每一行,您必须为 num_cols
分配 space整数,所以你可以看到循环将生成总共 num_rows * num cols
个整数,它们的分配方式允许你使用数组索引符号(在这种情况下是二维的——外部维度中的每个元素指向'row' 的开始,它包含指向 'column' 开始的指针,因此是双指针)以访问元素。我知道这可能令人困惑,这就是为什么我试图用这么多不同的方式来描述它 times/ways,但请提出任何问题,尤其是关于您特别不理解的问题,我将非常乐意与您一起帮助理解它。
我并不是说您必须以这种方式创建二维数组;你的方式也很好,我只是想向你展示这种方式,因为你很可能 运行 喜欢它,因为它很常见。
此外,请查看 Valgrind。您可以使用该工具查看您是否忘记了任何 free()
s/是否有一个不匹配的 malloc()
,并让您知道是否有任何已分配的内存 unreachable/leaked(可能之前更改了指针对 free()
的调用,因此调用无法正确释放内存,导致内存泄漏。
您必须为每个 malloc
调用一次 free
。您的代码有一个 malloc
和一个 free
(具有相同的地址)所以它是正确的。
RastaJedi - 需要注意的另外两点:
在调用 free() 之后,将 free'd 变量设置为 NULL 是个好主意,这有助于防止在 free 之后使用。
另外,如果你在一个代码块中 malloc,然后在一些被调用的函数中释放,然后从该函数中释放 return,有时 C 会忘记最后的释放(在你的例子中, free(arr) ),你应该在 return.
时将变量设置为 NULL
我来到这里,并验证了我在我正在处理的代码中编写的 malloc 和 free 调用确实与您的“常见”方式完全相同,但是 运行 进入了段错误,因为我在 main 中使用 malloc,从接收数组的双间接头的辅助函数中释放。将所有这些都包装在用于用户交互的 while 循环中,第二次传递是检查数组头是否为 NULL,但没有将其视为 NULL,尽管在辅助函数中明确设置为 NULL。使用调试器抓取代码是我识别行为的方式,也是我前来寻找的原因。
释放后,内存可用,并以不同方式(随机)重新分配;当带有 free() 的函数调用 returns 时,分配的内存已被释放,但调用代码似乎仍持有指向内存中该位置的指针。然后存在一个可能的竞争条件;到调用代码重新获得控制权时,对于用于数组头的变量所指向的位置无法保证,因此在函数 returns 之后将变量设置为 NULL 是一个非常好的主意。
虽然您可以使用 malloc 的指针来传递引用行为,但在某个函数内调用 free() 之后,引用行为会中断(因为被引用的东西是免费的' d).
所以,谢谢你的回答,这证实了我看错了我的问题部分 - 只是想也许其他人可能会在这里遇到问题,并且可能遇到与我相同的问题。
我正在用 C 语言创建一个二维数组;我是否正确释放它?
// 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);
对于每个 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
指针都指向 'column' 的起始地址)。所以外部维度中的每个元素指向一行,而在每一行中,内部维度('columns')中有num_cols
个元素,这只是一组num_cols
个整数。你能理解这个吗?因此,您必须分配 num_rows
个整数指针,并且每个指针都指向该行的第一个 'column'——对于每一行,您必须为 num_cols
分配 space整数,所以你可以看到循环将生成总共 num_rows * num cols
个整数,它们的分配方式允许你使用数组索引符号(在这种情况下是二维的——外部维度中的每个元素指向'row' 的开始,它包含指向 'column' 开始的指针,因此是双指针)以访问元素。我知道这可能令人困惑,这就是为什么我试图用这么多不同的方式来描述它 times/ways,但请提出任何问题,尤其是关于您特别不理解的问题,我将非常乐意与您一起帮助理解它。
我并不是说您必须以这种方式创建二维数组;你的方式也很好,我只是想向你展示这种方式,因为你很可能 运行 喜欢它,因为它很常见。
此外,请查看 Valgrind。您可以使用该工具查看您是否忘记了任何 free()
s/是否有一个不匹配的 malloc()
,并让您知道是否有任何已分配的内存 unreachable/leaked(可能之前更改了指针对 free()
的调用,因此调用无法正确释放内存,导致内存泄漏。
您必须为每个 malloc
调用一次 free
。您的代码有一个 malloc
和一个 free
(具有相同的地址)所以它是正确的。
RastaJedi - 需要注意的另外两点: 在调用 free() 之后,将 free'd 变量设置为 NULL 是个好主意,这有助于防止在 free 之后使用。 另外,如果你在一个代码块中 malloc,然后在一些被调用的函数中释放,然后从该函数中释放 return,有时 C 会忘记最后的释放(在你的例子中, free(arr) ),你应该在 return.
时将变量设置为 NULL我来到这里,并验证了我在我正在处理的代码中编写的 malloc 和 free 调用确实与您的“常见”方式完全相同,但是 运行 进入了段错误,因为我在 main 中使用 malloc,从接收数组的双间接头的辅助函数中释放。将所有这些都包装在用于用户交互的 while 循环中,第二次传递是检查数组头是否为 NULL,但没有将其视为 NULL,尽管在辅助函数中明确设置为 NULL。使用调试器抓取代码是我识别行为的方式,也是我前来寻找的原因。
释放后,内存可用,并以不同方式(随机)重新分配;当带有 free() 的函数调用 returns 时,分配的内存已被释放,但调用代码似乎仍持有指向内存中该位置的指针。然后存在一个可能的竞争条件;到调用代码重新获得控制权时,对于用于数组头的变量所指向的位置无法保证,因此在函数 returns 之后将变量设置为 NULL 是一个非常好的主意。
虽然您可以使用 malloc 的指针来传递引用行为,但在某个函数内调用 free() 之后,引用行为会中断(因为被引用的东西是免费的' d).
所以,谢谢你的回答,这证实了我看错了我的问题部分 - 只是想也许其他人可能会在这里遇到问题,并且可能遇到与我相同的问题。