为什么下面的代码不产生分段错误?

Why doesn't the following code produce a segmentation fault?

本文关键字:分段 错误 代码 为什么      更新时间:2023-10-16
#include <iostream>
using namespace std;
int a[4];
int main(){
    int b=7;
    cout<<a[b]<<endl;
    return 0;
}

我试图访问未分配的内存。所以我期望输出是一个分割错误,而不是输出是一些垃圾值。

后来我将'b'增加到1000,现在输出是'Segmentation fault'。这种行为有什么特别的原因吗?

如果您试图访问不存在的内存地址(进程的地址空间之外),可能会抛出分段错误。

在这种情况下,

a[7]可能不在其可访问空间之外,但a[1000]肯定在。但即使是前者也会在你最意想不到的时候爆炸;)

只有在访问操作系统不允许访问的内存时才会出现分段错误。

然而,你可以访问内存,虽然它不是你期望的,已经授予你,例如内存地址指向较早或较晚的堆栈。但是你不能指望它是一致的,因为本地存储的变量如何放在堆栈上是由编译器根据神秘的优化来决定的,这些优化会随着代码的变化而变化——从调试到发布,等等。

但是如果你曾经看到过这样的情况,"为什么访问这个变量会给我垃圾,但总是相同的垃圾?"

你可能无意中看到了不该看到的部分。

这是未定义的行为,所以任何事情都可能发生,你只是不能告诉。查看this out (c++)以了解未定义行为,未指定行为和实现定义行为之间的区别。

附件J

C - **ISO C9899**对此有明确论述。

编辑
c++ - N3485 ISO/IEC1.9.2, 1.9.3, 1.9.4章节中讨论了上述行为

越界访问是未定义的行为。它可以访问进程空间中的任意内存。如果访问的内存没有分配或不在进程地址空间中(可能在内核中),那么您的程序将因分段错误而崩溃。在这种情况下,错误将帮助您识别问题,如果幸运的话会导致崩溃,否则它可能会被忽视,并且会在程序中得到一些错误,这些错误会破坏内存,然后难以跟踪。a[1000]未分配的概率更高,从而导致崩溃。

未定义的行为不需要引起段错误。考虑int i = INT_MAX + 1;的另一个未定义行为的例子,它通常不会导致段错误。