为什么我没有得到分段错误?

时间:2012-10-11 22:10:50

标签: c segmentation-fault cstring

  

可能重复:
  Why don’t I get a segmentation fault when I write beyond the end of an array?

当我意识到发生了一些奇怪的事情时,我只是在玩指针。我知道每当我们想要将字符串 src 复制到另一个字符串 dst 时,使用 strcpy ,我们应该分配所需的空间对于 src

    char *dst,*src = "asdlskafksdhfklshfkshdkfhksdhfçsahdflçsdhfçklshadfç";

    dst = (char*)malloc(1); //only one char allocated
    strcpy(dst,src);

    printf("dst=%s.\n",dst);

此代码不应执行。然而,这没有发生。代码执行,将 src 成功复制到 dst 并像魅力一样打印 dst 。你们有人可以解释一下为什么会这样吗?

4 个答案:

答案 0 :(得分:2)

C的部分性能是内置错误检查的方式不多。所有strcpy都知道它传递了一个正确类型的指针,它不知道它指向了多少分配的内存。生成的机器代码只是从src指针读取到第一个空字节,然后将其粘贴到dst指针中。如果它没有覆盖别人的记忆,那就没有错误。

什么是“别人的记忆”?通常,在pages中为进程分配内存。当你对一个字节进行malloc时,该进程被给予一整页内存,可能只有几千字节,可以根据需要进行切片和切块。当您的进程尝试在其分配的页面and for other reasons之外写入时,会发生分段错误。该错误通常由正在进行存储器管理的操作系统和/或硬件生成。由于src只有几十个字节,因此不太可能走出进程页面。如果你让src成为一个更长的字符串,你可能会得到你期望的段错误。

有各种用于调试的malloc包装器库,通过各种技巧,使C检查内存错误。 ValgrindElectric Fence是最有名的。

PS我对这些东西究竟是如何工作有点朦胧,但它比“它的未定义行为”更令人满意。请随时编辑我缺乏解释的地方。

答案 1 :(得分:2)

您的字符串在堆上分配。堆的大小不只有1个字节,而是大约4kb的物理RAM(默认的Windows控制台应用程序大小)。

尝试写入堆外部的内存区域时,只会出现分段错误。 但是,您可能会破坏应用程序其他部分的内存。但是,由于您的程序非常小,并且在写入超出分配的内存之后终止,您不太可能看到任何错误

答案 2 :(得分:1)

在发布版本* dst指向进程地址空间的某些内存 - 你写的是,如果碰巧被像你的应用程序这样有用的东西占用它会崩溃。

在调试版本中,你的编译器可能会将* dst设置为0或某些可识别的值,如0xDEADBEEF,这样你就可以发现它。

答案 3 :(得分:1)

如果在外部分配的内存中写入,则结果未定义。如果你很幸运,你会遇到段错误。如果你运气不好,其他变量都会被覆盖。底线:一切顺利!