微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

为什么再写一个数组成员会引起问题?

如何解决为什么再写一个数组成员会引起问题?

以下代码似乎运行良好:

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

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

解决方法

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

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

但是不是指向char的5个指针,它们更大。
让我们假设指针是四个字节(可以是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);。不必编写该类型,从而减少了出错的可能性。

不必键入类型的部分包括指针/星号数量的潜在错误部分。即这种最佳做法可以避免您遇到的问题。

,

sizeof( char )始终等于1。所以在这次的malloc调用中

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

您为5个字节分配了一个内存。

但是您正在使用此内存范围来存储指针,这些指针通常可以等于48字节,具体取决于所使用的系统。

因此,您正在访问超出分配范围的内存。结果,该程序具有未定义的行为。

你需要写

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

或者您可以写

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

在64位系统中,我想可能是您的情况,通常是8个字节的指针,您的内存分配仅保留5个''' <root> <Title ref="111111"> <Events> <Event type="change"/> </Events> <tag1>John</tag1> <tag2>A.</tag2> <tag3>Smith</tag3> </Title> <Title ref="222222"> <Events> <Event type="cancel"/> </Events> <tag1>Bob</tag1> <tag2>B.</tag2> <tag3>Hope</tag3> </Title> <Title ref="333333"> <Events> <Event type="change"/> </Events> <tag1>Julie</tag1> <tag2>A.</tag2> <tag3>Moore</tag3> </Title> <Title ref="444444"> <Events> <Event type="cancel"/> </Events> <tag1>First</tag1> <tag2>M</tag2> <tag3>Last</tag3> </Title> </root> ''' s的空间,而这仅是5个字节,甚至没有足以容纳一个指针,更不用说四个指针了。

对我来说,令人惊讶的是它在第一或第二作业中不会中断。

达成共识的方法是使用将内存分配给它的指针的解引用名称作为sizeof的参数,正是为了避免类似您遇到的问题:

char

不仅避免了错误,而且还使代码更具可维护性。

,

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

添加一些代码以检查正在发生的事情。

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

    printf("allocated : %zu bytes\n",sizeof(char) * 5);
    printf("used : %zu bytes\n",sizeof(s[0]) + sizeof(s[1]) + sizeof(s[2]) + sizeof(s[3]));
    printf("Is the allocated memory big enough?\n");
    return s;
}

https://godbolt.org/z/9aqYKb

allocated : 5 bytes
used : 32 bytes
Is the allocated memory big enough?

它能回答您的问题吗?

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。