我正在使用malloc
动态分配2d char数组。除非在free()
之前将每个数组索引都设置为NULL,否则在尝试free()
时会遇到分段错误。为什么会出现细分错误?
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int nrows = 20; int ncolumns = 10;
char ** arr = malloc(nrows * sizeof(char *));
for(int i = 0; i < nrows; i++)
arr[i] = malloc(ncolumns * sizeof(char));
arr[0] = "string1";
arr[1] = "string2";
// does not work without the following code:
// for(int i = 0; i < 20; i++)
// arr[i] = NULL;
for(int i = 0; i < 20; i++)
free(arr[i]);
free(arr);
return 0;
}
答案 0 :(得分:3)
执行此操作时:
arr[0] = "string1";
arr[1] = "string2";
您用两个字符串常量的地址覆盖了arr[0]
和arr[1]
的内容,它们包含从malloc
返回的内存地址。这将导致内存泄漏,因为无法再访问该内存。这也是调用free
时崩溃的原因,因为这些变量不再保存分配的内存的地址。
您可能想在这里使用strcpy
,它将把字符串文字的内容复制到您分配的内存中。
strcpy(arr[0], "string1");
strcpy(arr[1], "string2");
现在您可以正确free
记忆了。
答案 1 :(得分:3)
您的代码正常,问题出在以下事实:您正在将字符串 literal 分配给以下位置的数组:arr[0] = "string1";
。
因此,您正在用指向字符串文字的指针替换arr[0]
处的指针,该指针指向分配的内存。
文字的指针受到保护,您不能释放(也不能写入)它们,因为您没有分配它们。
要解决此问题,请使用strcpy
将文字的值复制到分配的内存中:
strcpy(arr[0], "string1");
strcpy(arr[1], "string2");
答案 2 :(得分:1)
=
运算符不会复制仅分配指针的字符串。因此,您无法再为那些数组元素访问您分配的内存,并尝试释放它是一个不确定的行为,可能会导致段错误。
您需要使用strcpy
复制它。
答案 3 :(得分:1)
两件事要知道:
从malloc获取的每个资源的规则都必须释放它。 要释放,只需调用free函数即可(但我们可以选择分配空指针以确保它已释放)。
char * a = malloc(255);
免费
free(a);/* this is mandatory */
a = NULL;/* we can add this to the first line */
实际上,您习惯于分配NULL值,并且一旦访问它的值,您将有NULL引用错误:这样您就知道在哪里找到错误了
您尝试执行的操作:
分配一个数组char ** arr = malloc(nrows * sizeof(char *));
,然后释放它free(arr);
但是您分配了20个字符数组arr[i] = malloc(ncolumns * sizeof(char));
您忽略了它的值arr[0] = "string1";
(您松开了malloc返回的值,因此现在无法释放arr [0])我们不在C ++中。因此,“ string1”存储在堆栈中(因此malloc无法释放它)
然后您可以免费拨打电话。
你能做什么
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int nrows = 20; int ncolumns = 10;
char ** arr = malloc(nrows * sizeof(char *));
for(int i = 0; i < nrows; i++)
arr[i] = malloc(ncolumns * sizeof(char));
free(arr[0]);//know we can loose it value because it is freed
arr[0] = NULL;// in fact we assign a value just after so this line is useless but is educationnal purpose
free(arr[1]);//know we can loose it value because it is freed
arr[1] = NULL;// in fact we assign a value just after so this line is useless but is educationnal purpose
arr[0] = "string1";
arr[1] = "string2";
// does not work without the following code:
// for(int i = 0; i < 20; i++)
// arr[i] = NULL;
for(int i = 2; i < 20; i++)//we start at 2 because the first two value are on the stack
{
free(arr[i]);
arr[i] = NULL;//this is useless because we will free arr just after the loop)
}
free(arr);
arr = NULL;// this is useless because we exit the end of program
return 0;
}
答案 4 :(得分:1)
调用free
时发生崩溃,这表明代码中其他地方的内存管理不正确。当您将指针设置为NULL
然后指向free
时,您不会崩溃,因为C标准§7.22.3.3确保free(NULL)
是良性的:
7.22.3.3免费功能
... 如果ptr是空指针,则不执行任何操作。否则,如果 该参数与内存管理器返回的指针较早版本不匹配 函数,或者如果通过调用free或realloc释放了空间,则 行为是不确定的。
强调我的。
正如其他答案所指出的那样,您试图在未使用free
系列功能显式分配的内存上调用malloc
(因为您将arr[i]
指针改写为字符串文字)