C`Abort trap:6`仅在某些条件下

C`Abort trap:6`仅在某些条件下,c,arrays,string,pointers,char,C,Arrays,String,Pointers,Char,我知道当你在写你不拥有的部分内存时,会出现中止陷阱6,但我在做K&R练习时发现了一些有趣的事情 /* strcat: copies t to the end of s */ void _strcat(char *s, char *t) { while (*s != '\0') { s++; } while ((*s++ = *t++) != '\0') { } } #include <stdio.h> int main() { c

我知道当你在写你不拥有的部分内存时,会出现中止陷阱6,但我在做K&R练习时发现了一些有趣的事情

/* strcat:  copies t to the end of s */
void _strcat(char *s, char *t) {
    while (*s != '\0') { 
        s++;
    }
    while ((*s++ = *t++) != '\0') { }
}

#include <stdio.h>
int main() {
    char s[7] = "hello, ";
    char *t = "world";

    _strcat(s, t);
    printf("%s\n", s);
    return 0;
}
感兴趣的部分是char s[7]=hello

当数组大小为7时,不会打印hello,Abort trap 6的确切长度,即使_strcat在内存的初始化部分之外添加字符

8-12(含8-12)之间的任何数字都会给出中止陷阱6,而>=13的数字则可以

因此产生了两个问题:

为什么char s[12]=你好,不好,而7是?看起来尾随“\0”需要一个大小为13的数组,但为什么7可以呢?不是应该是8点吗? 为什么7一开始就可以?大小8-12包含hello,就像大小7的字符数组一样,它们的写入超出了原始数组的大小,而7却可以成功,而其他的则不能。
你必须读机器代码才能弄明白这一点。正如乔纳森·莱夫勒所说,这是一种未定义的行为

这可能取决于编译器以及它在内存中的布局方式。不要求大小为7的数组获得实际的7字节。它可能会决定将其填充到16,以获得更好的堆栈布局。或者它可能会把它放在一个不同的位置,所以在它后面有一个零和一些额外的空间,而较大的阵列得到不同的位置

或者,如果在启用优化的情况下编译,编译器可能会将大小为7的循环展开为正确的代码,从而简化为一个简单的putshello,world;但无法内联更大的循环

出于好奇,我做了一个小实验,在Linux上使用GCC时,答案是在64位模式下它总是有效的,因为8字节的char*t指针中有足够的空间指向存储世界


在32位模式下,正如您所描述的,它会失败,因为它会覆盖返回堆栈。但是对于垃圾数据,7是可以工作的,因为它在超过返回值之前不会找到零,然后它会附加到开放的堆栈空间中。打印的结果看起来像hello,��M�?��world

我不知道您使用的是哪种编译器,但xcode对此表示不满


初始值设定项-字符数组的字符串太长

未定义的行为不必具有一致或正常的结果。你调用了未定义的行为;您得到了您得到的。@JonathanLeffler哪部分会导致未定义的行为?当您向大小为7的数组中添加5个字符时,该数组甚至不是以null结尾的字符串。F'r'实例。@JonathanLeffler谢谢你,我正在使用gcc编译器