为什么strcpy没有分段错误?

时间:2012-01-27 17:34:26

标签: c stack-overflow c99 strcpy

  

可能重复:
  Undefined, unspecified and implementation-defined behavior

这应该是错误的。为什么不呢。

    #include <string.h>
    #include <stdio.h>

    char str1[] = "Sample string. Sample string. Sample string. Sample string. Sample string. ";
    char str2[2];

    int main ()
    {
      strcpy (str2,str1);
      printf("%s\n", str2);
      return 0;
    }

我正在使用gcc版本4.4.3以及以下命令:

    gcc -std=c99 testString.c -o test

我也尝试将优化设置为o(-O0)。

5 个答案:

答案 0 :(得分:8)

  

这应该是错误的

没有理由&#34;应该&#34;段错误。代码的行为是未定义的。这并不意味着它必然会崩溃。

答案 1 :(得分:4)

只有当您执行操作系统知道您不应该访问的内存时,才会发生分段错误。

所以,可能发生的是,操作系统在页面中分配内存(通常在4KiB左右)。 str2可能与str1位于同一页面上,并且您没有在页面末尾运行,因此操作系统不会注意到。

这是关于未定义行为的事情。任何事情都可能发生。现在,该程序实际上在您的机器上“有效”。明天,str2可能会放在页面的末尾,然后是段错误。或者,你可能会在内存中覆盖其他内容,并且会产生完全不可预测的结果。

编辑:如何导致段错误:

两种方式。一个仍然是未定义的行为,另一个不是。

int main() {
    *((volatile char *)0) = 42; /* undefined behavior, but normally segfaults */
}

或者以定义的方式进行:

#include <signal.h>

int main() {
    raise(SIGSEGV); /* segfault using defined behavior */
}

编辑:segfault的第三和第四种方式

以下是使用strcpy的第一种方法的变体:

#include <string.h>

const char src[] = "hello, world";
int main() {
    strcpy(0, src); /* undefined */
}

这个变种只会因-O0

而崩溃
#include <string.h>

const char src[] = "hello, world";
int main() {
    char too_short[1];
    strcpy(too_short, src); /* smashes stack; undefined */
}

答案 2 :(得分:2)

您的程序写入超出数组的分配范围,这会导致未定义行为
该程序是不正确的,它可能会崩溃或可能不会。可能会或可能不会解释。

它可能不会崩溃,因为它会覆盖一些超出未使用的数组边界的内存,但是一旦该内存的合法所有者试图访问它就会崩溃。

答案 3 :(得分:1)

段错误 保证 行为。

这是一个可能的(有时可能)做坏事的结果。
另一种可能的结果是,它运作纯粹。第三种可能的结果是鼻子恶魔。

答案 4 :(得分:0)

如果你真的想知道这可能是什么腐败我会建议你看看覆盖内存后面会产生一个链接器映射文件应该给你一个公平的想法但是这一切都取决于事情是如何奠定的在内存中,甚至可以尝试使用gdb运行它来解释为什么它会发生或不发生段错误,也就是说,访问违规(HW辅助)中构建检查的粒度不能比页面更精细,除非引入一些软件魔法(即使使用此页面粒度访问检查,可能会发生紧接的下一页确实指向您正在执行的程序的其他内容并且它是可写页面),知道valgrind的人可以解释它是如何能够检测这样的访问违规(也是libefence),很可能(我可能是非常错误的解释,纠正我,如果我错了!)它使用某种形式的标记或比较来检查是否发生了越界访问。