我编写了这段代码并且期待一个分段错误,但似乎我可以访问我不应该访问的内存块。
#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));
不会改变任何内容......
谢谢,祝贺。
答案 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)
超出数组末尾的访问是未定义的行为。 任何都可能发生。它可能会工作,可能会失败,它可能会重新格式化您的硬盘驱动器,或者它可能会在堆栈溢出时发布问题。
有时会出现故障