首页 > 解决方案 > 为什么写入另一个数组成员会导致问题?

问题描述

以下代码似乎运行良好:

char **func()
{
    char **s = malloc(sizeof(char) * 5);
    
    s[0] = "1101";
    s[1] = "1001";
    s[2] = "0001";
    // s[3] = "1100";
    return s;
}

int main()
{
    char **s;
    s = func();
    printf("Hello World: %s", s[0]);
    free(s);

    return 0;
}

但是,如果我取消注释该行s[3] = "1100";,则会出现错误:

Error in `./a.out': free(): invalid next size (fast): 0x000000000259f010

为什么会这样,即使数组有足够的大小?

标签: cstringfunctionpointersmalloc

解决方案


在这里,您为 5char秒分配了足够的内存。

char **s = malloc(sizeof(char) * 5);

然而,对于 5 个char更大的指针来说不是。
让我们假设指针是四个字节(可能是 8...)。字符绝对是 1 个字节。

在这里,您正在写入该内存,大约 4 个字节(因为指针的大小,而不是因为四个字符)。
还不是问题。 s[0] = "1101";

在这里,您正在写入位于高 4 字节地址的内存中。
该地址本身还不是问题,它仍然在 5 个分配的字节内。
但是,在那里写入大于一个字节的内容(您这样做,大小为 4)已经不正确。 s[1] = "1001";

更糟糕的是,在你得到的地址后面 8 个字节,在所有地址后面 3 个字节,总共 4 个字节。非常不正确。 s[2] = "0001";

您可能已经遇到了第二次写入的问题。
第二次和第三次访问没有遇到问题纯属运气。好运或坏运,取决于您喜欢何时发现错误的理念。

要解决此问题,请根据您正在编写的内容分配内存。引用 Barmar 的评论:

sizeof(char) 应该是 sizeof(char *)
如果 malloc 中 sizeof 的参数是一个类型,它应该总是比你分配的类型少一个 *。

来自 Deduplicator(我实际上也更喜欢这个):

我更希望看到 char** s = malloc(5 * sizeof *s);。不必编写类型使其不易出错。

不必键入类型的部分包括指针/星号数量的潜在错误部分。即这个最佳实践会阻止你的问题。


推荐阅读