#include <iostream>
using namespace std;
int a[4];
int main(){
int b=7;
cout<<a[b]<<endl;
return 0;
}
我试图访问未分配的内存。所以我希望输出是分段错误,而不是输出是一些垃圾值。
后来我将'b'增加到1000,现在输出是'Segmentation fault'。这种行为有特定的原因吗?
我正在使用 gcc-4.3.2 编译器。
#include <iostream>
using namespace std;
int a[4];
int main(){
int b=7;
cout<<a[b]<<endl;
return 0;
}
我试图访问未分配的内存。所以我希望输出是分段错误,而不是输出是一些垃圾值。
后来我将'b'增加到1000,现在输出是'Segmentation fault'。这种行为有特定的原因吗?
我正在使用 gcc-4.3.2 编译器。
如果您尝试访问不存在的内存地址(外部进程的地址空间) ,则可能会引发分段错误。
a[7]
在这种情况下,可能不在其可访问空间之外,但a[1000]
最肯定的是。但即使是前者也会在你最意想不到的时候爆炸;)
仅当您访问操作系统不允许您访问的内存时,才会发生分段错误。
但是,您可以访问虽然不是您期望的,但已授予您的内存,例如指向堆栈的较早或较晚的内存地址。但这不是您可以依赖的一致的东西,因为本地存储的变量如何放置在堆栈上是由编译器根据会有所不同的神秘优化决定的 - 从调试到发布,随着代码的更改等。
但是,如果您曾经看到类似的内容,“为什么访问这个变量会给我带来垃圾,但总是同样的垃圾?” 你可能无意中偷看了你不应该偷看的堆栈部分。
这是未定义的行为,所以任何事情都可能发生,你无法判断。检查一下(对于 C++)以了解未定义行为、未指定行为和实现定义行为之间的区别。
C -**ISO C9899**
在附件 J 中清楚地谈到了这一点。
编辑
C++ -在,N3485 ISO/IEC
部分1.9.2
中讨论上述行为。1.9.3
1.9.4
越界访问是未定义的行为。它可以访问进程空间中的任意内存。如果访问的内存未分配或不在进程地址空间中(可能在内核中),那么您的程序将因分段错误而崩溃。在这种情况下,故障将帮助您识别问题,如果幸运的话会崩溃,否则它可能会被忽视,并且稍后会在程序损坏内存中出现一些错误,然后难以跟踪。a[1000] 未分配的概率更高,因此崩溃。内存是按页分配的。
未定义的行为不需要导致段错误。考虑int i = INT_MAX + 1;
另一个通常不会导致段错误的未定义行为示例。