#include <stdio.h>
int main(void)
{
char a[100] = "hi";
strcat(a, a);
strcat(a, a);
printf("%s\n", a);
return 0;
}
根据C语言标准中strcat
的定义,§7.21.3.1/2
如果在重叠对象之间进行复制,则行为是未定义的。
即使只执行一次,我的编译器也会崩溃,因为strcat(a, a);
会将第二个参数的第一个字符复制到第一个参数末尾的'\0'上,然后将第二个参数的第二个字符复制到它后面,以此类推,直到在第二个参数中遇到'\0'为止...但这永远不会发生,因为当第一个字符被复制时,'\0'已经消失了。
来自strcat(3)手册页:
描述
strcat()和strncat()函数将空字符结尾的字符串s2的副本附加到空字符结尾的字符串s1的末尾,然后添加一个终止符'\0'。字符串s1必须有足够的空间来容纳结果。
strncat()函数从s2附加不超过n个字符,然后添加一个终止符'\0'。
源字符串和目标字符串不应重叠,因为行为未定义。
这是未定义行为。
如果你正在循环中,从字符串中读取每个char
字符,直到找到\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}
...
因为您覆盖了空终止符,所以您的源字符串永远不会结束,该方法将继续复制,直到尝试访问不应访问的内存并导致段错误。