C`中止陷阱:6`仅在某些条件下

时间:2017-08-10 00:46:16

标签: c arrays string pointers char

我理解Abort trap 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之间的任何数字(包括)都会得到Abort trap 6,而<> = 13的数字则可以。

因此出现了两个问题:

  1. char s[12] = "hello, "为什么7不合适?尾随13似乎需要一个大小为'\0'的数组,但为什么7可以呢?不应该是8?
  2. 为什么7首先是好的?大小8-12包含"hello, ",就像一个7号字符大小的数组一样,并且写得超出了它们原来的数组大小,但是7却没有使用它,而其他人没有。

2 个答案:

答案 0 :(得分:1)

你必须阅读机器代码来解决这个问题。正如Jonathan Leffler所说,这是不确定的行为。

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

或者如果您使用优化进行编译,编译器可能会将大小为7的循环展开为“正确”代码,这会减少为简单puts("hello, world");,但无法内联更大的循环。

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

在32位模式下,它会因为您描述而失败,因为它会覆盖返回堆栈。但是有7种工作,有垃圾数据,因为它在超过返回值之前没有找到零,然后它“追加”到开放堆栈空间。打印结果类似于hello, ��#m�?��world

答案 1 :(得分:0)

我不知道你使用的是哪个编译器,但xcode抱怨它

Initializer error char数组的初始化器 - 字符串太长