访问超出内存后,分段错误不会立即出现
我编写了这段代码并且期待一个段落故障,但似乎我被允许访问我不应该访问的内存块。
#include 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
并声明int * tab = (int*)malloc(sizeof(int));
什么都不改变……
谢谢,最好的。
您的数组tab
将位于堆栈的某个位置。 当您打印超过数组的末尾时,实际上是打印堆栈上其他内存位置的值。
需要大约1000次迭代才能获得seg错误的原因是堆栈是在页面中映射的,而页面的大小通常是4 KB。 一旦你读了大约1000个整数,你就会超过4000个字节,你已经越过了一个未映射的页面。 从未映射的页面读取实际上是触发seg错误的原因。
请注意,我只是解释您系统上发生的事情。 无法保证堆栈将在页面中映射,或者页面大小为4 KB。 从技术上讲,您正在触发未定义的行为,任何事情都可能发生。 你可能会发现做printf("%p\n", &tab[i]);
很有启发性printf("%p\n", &tab[i]);
在每次迭代时,看看在得到seg故障之前它打印的最后一个地址是什么。 如果我对4 KB页面是正确的,那么您看到的最后一个地址将以ffc
结尾,因为这将是页面上的最后4个字节。
当您使用越界内存时,您将面临Undefined behavior
。 您无法定义称为Undefined behavior
。
在你的情况下,它发生在i = 1000
s,在其他情况下它可能很好地发生在i=347
左右。
分段错误是访问程序允许的堆栈地址空间之外的内存的结果。 如果您在该内存范围内完成执行,它可能会正常运行并让您感到惊讶。 一个越界访问可能会产生虚拟内存访问,直到您没有穿过堆栈内存区域。
如果你遇到分段错误,请考虑自己很幸运 ,因为这会告诉你,有些事情是错误的。 否则,你不知道由此产生的恐怖。
注意:作为一个建议,问题标题应该改为.. comes up very late
或类似的东西
您正在访问tab
边界之外,但您仍然在自己的堆栈空间中(可能是因为堆栈帧大于一个字节)。 您可以在自己的堆栈上拥有完全读/写访问权限。 事实上,这是许多裂缝可能发生的原因。
当您离开自己的堆栈边界时,会发生分段错误。 那是您尝试访问不属于您的细分市场的那一刻(因此称为“细分错误”)。
访问数组越界将导致未定义的行为。 你在i=1000
看到这个
检查此链接: 访问数组越界有多危险?
超出数组末尾的访问是未定义的行为。 什么都可能发生。 它可能会工作,它可能会失败,它可能会重新格式化您的硬盘驱动器或它可能会发布有关堆栈溢出的问题。
有时会出现故障