将字符串与自身连接两次会导致分段错误

3
#include <stdio.h>

int main(void)
{
    char a[100] = "hi";

    strcat(a, a);
    strcat(a, a);

    printf("%s\n", a);

    return 0;
}

代码审查严格针对可运行的代码。我已将您的问题迁移到我们的姊妹站点,该站点是相关主题的适当场所。 - Winston Ewert
4个回答

9

根据C语言标准中strcat的定义,§7.21.3.1/2

如果在重叠对象之间进行复制,则行为是未定义的。

即使只执行一次,我的编译器也会崩溃,因为strcat(a, a);会将第二个参数的第一个字符复制到第一个参数末尾的'\0'上,然后将第二个参数的第二个字符复制到它后面,以此类推,直到在第二个参数中遇到'\0'为止...但这永远不会发生,因为当第一个字符被复制时,'\0'已经消失了。


5

来自strcat(3)手册页:

描述

strcat()和strncat()函数将空字符结尾的字符串s2的副本附加到空字符结尾的字符串s1的末尾,然后添加一个终止符'\0'。字符串s1必须有足够的空间来容纳结果。

strncat()函数从s2附加不超过n个字符,然后添加一个终止符'\0'。

源字符串和目标字符串不应重叠,因为行为未定义。


2

这是未定义行为。

如果你正在循环中,从字符串中读取每个char字符,直到找到\0,但同时又在末尾添加(写入)字符,那么循环何时结束呢?


0

我怀疑这是因为实现正在覆盖末尾的空字节:

Start: a = {h,i,\0}
         src^   vdst
next:  a = {h,i,h}
           src^   vdst
next:  a = {h,i,h,i}
             src^   vdst
next:  a = {h,i,h,i,h}
...

因为您覆盖了空终止符,所以您的源字符串永远不会结束,该方法将继续复制,直到尝试访问不应访问的内存并导致段错误。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接