访问超出内存后,分段错误不会立即出现

时间:2014-12-03 10:29:20

标签: c arrays segmentation-fault indexoutofboundsexception

我编写了这段代码并且期待一个分段错误,但似乎我可以访问我不应该访问的内存块。

#include<stdio.h>
int main()
{
    int tab[1];
    tab[0]=42;
    int i;
    //Expecting Seg Fault from i==1...
    for(i=0;;i++)
    {
        printf("%d \t %d \n", i, tab[i]);
    }
    return 0;
}

我正在编译:

gcc -Wall -Wextra my_code.c -o segfault && ./segfault

执行后,变量i在我收到分段错误之前达到1000的值。

我的问题是:为什么到目前为止我能阅读tab

PS:使用#include <stdlib.h>并声明int * tab = (int*)malloc(sizeof(int));不会改变任何内容......

谢谢,祝贺。

5 个答案:

答案 0 :(得分:3)

当您使用越界内存时,您将面临Undefined behavior。您无法定义名为Undefined behavior的内容。

在你的情况下,它发生在i = 1000 s,在其他情况下,它可能恰好发生在i=347左右。

分段错误是访问程序允许的堆栈地址空间之外的内存的结果。如果您在该内存范围内完成执行,可能正常运行并使用明显的正确工作给您带来惊喜。 out-of-bound访问权限可以生成 vaild 内存访问权限,直到您没有越过堆栈内存区域。

如果你遇到分段错误,请考虑自己幸运,因为这告诉你,有些事情是错误的。否则,你不知道由此产生的恐怖。

注意:作为建议,问题标题应更改为.. comes up very late或类似的东西

答案 1 :(得分:2)

您的数组tab将位于堆栈的某个位置。当您打印超过数组的末尾时,实际上是打印堆栈中其他内存位置的值。

获得seg错误需要大约1000次迭代的原因是堆栈在页面中映射,页面大小通常为4 KB。一旦你读了大约1000个整数,你就会超过4000个字节,你已经越过了一个未映射的页面。从未映射的页面读取实际上是触发seg错误的原因。

请注意,我只是在解释您系统上发生的事情。无法保证堆栈将在页面中映射,或者页面大小为4 KB。从技术上讲,您正在触发未定义的行为,任何事情都可能发生。您可能会发现在每次迭代时执行printf("%p\n", &tab[i]);并看到在获得seg错误之前打印的最后一个地址是多少。如果我对4 KB的页面是正确的,那么您看到的最后一个地址将以ffc结尾,因为这将是页面上的最后4个字节。

答案 2 :(得分:0)

您正在tab的边界之外访问,但您仍然在自己的堆栈空间中(可能是因为堆栈帧大于一个字节)。您在自己的堆栈上具有完全读/写访问权限。事实上,这是许多裂缝可能发生的原因。

当您离开自己的堆栈边界时,会发生分段错误。这是您尝试访问不属于您的细分受众群的那一刻(因此名称&#34;细分错误&#34;)。

答案 3 :(得分:0)

访问数组越界将导致未定义的行为。 您在i=1000

看到此消息

检查此链接: How dangerous is it to access an array out of bounds?

答案 4 :(得分:0)

超出数组末尾的访问是未定义的行为。 任何都可能发生。它可能会工作,可能会失败,它可能会重新格式化您的硬盘驱动器,或者它可能会在堆栈溢出时发布问题。

有时会出现故障