为2d char数组动态分配内存

时间:2019-01-17 21:20:00

标签: c

我正在使用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;
}

5 个答案:

答案 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,realloc,calloc从堆分配资源。我只会说malloc(但是是一样的)
    • free只能从堆中释放资源。堆栈是编译器的存储库(它存储函数调用和其他数据)

从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]指针改写为字符串文字)