当我在数组末尾写入时,为什么不会出现分段错误?

sin*_*ngh 5 c++ segmentation-fault

为什么我编译时没有给出错误?

#include <iostream>
using namespace std;

int main()
{
    int *a = new int[2];
    // int a[2]; // even this is not giving error
    a[0] = 0;
    a[1] = 1;
    a[2] = 2;
    a[3] = 3;
    a[100] = 4;
    int b;

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

谁能解释为什么会这样.提前致谢.)

Luc*_*ore 10

因为未定义的行为==任何事情都可能发生.你不幸的是它不会崩溃,这种行为可能会隐藏错误.

至于a定义两次 - 这是编译器中的一个错误.


Mik*_*our 8

声明两个称为a肯定的变量是一个错误; 如果你的编译器接受了它,那么它就坏了.我假设你的意思是如果你用另一个声明替换一个声明,你仍然不会得到错误.

数组访问不是范围检查.在编译时,数组的大小通常是未知的,并且即使语言也不需要检查.在运行时,检查会降低性能,这将违背C++的理念,即不支付您不需要的东西.因此,超出数组末尾的访问会产生未定义的行为,并且程序员必须确保它不会发生.

有时,无效访问会导致分段错误,但这不能保证.通常,内存保护仅适用于整页内存,典型页面大小为几千字节.将无法捕获有效内存页面内的任何访问权限.您访问的内存很可能包含一些其他程序变量或调用堆栈的一部分,因此写入可能会以您能想象的任何方式影响程序的行为.

如果您想要安全,可以使用std::vector,并且只能使用其at()功能访问其元素.这将检查索引,如果超出范围则抛出异常.它还将为您管理内存分配,修复示例中的内存泄漏.


oop*_*psi 5

我猜你来自 Java 或类似 Java 的语言,一旦你走出数组的边界,你就会得到“数组索引越界”异常。

好吧,C 对你的期望更高;它节省了您要求的空间,但它不会检查您是否超出了节省的空间的边界。一旦你按照上面提到的那样做,程序就会出现可怕的未定义行为。

并且记住,如果您的程序中有一个错误并且您似乎无法找到它,并且当您查看代码/调试它时,一切似乎都很好,那么您很有可能“出局”边界”并访问未分配的位置。