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

为什么我编译时不会出错?

#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; } 

有人可以解释为什么发生这种情况。 提前致谢。)

我猜你是从Java或类似Java的语言,一旦你走出数组的边界,你会得到“数组索引越界”exception。

那么,C期待你更多; 它节省了你所要求的空间,但是不检查你是否超出了这个节省空间的边界。 一旦你这样做,如上所述,该程序有可怕的未定义的行为。

而且要记住,如果你的程序中有一个bug,而且你看起来无法find它,而且当你仔细阅读代码/debugging它时,一切似乎都没有问题,那么你很有可能“边界“和访问一个未分配的地方。

因为未定义的行为==什么都可能发生。 不幸的是,它不会崩溃,这种行为可能会隐藏错误。

至于定义两次 – 这是编译器中的一个错误。

声明两个variables肯定是一个错误; 如果你的编译器接受了,那么它就坏了。 我假设你的意思是,如果你用另一个声明replace一个声明,你仍然不会出错。

数组访问不被范围检查。 在编译时,数组的大小通常是不知道的,即使是这样,语言也不需要检查。 在运行时,检查会降低性能,这违背了C ++不支付不需要的东西的哲学。 因此,超出数组末尾的访问会导致未定义的行为,并由程序员来确保不会发生。

有时,无效的访问会导致分段错误,但这不能保证。 通常,内存保护仅适用于整个内存页面,典型页面大小为几千字节。 有效内存页面内的任何访问都不会被捕获。 很有可能你访问的内存包含一些其他的程序variables或者调用堆栈的一部分,所以在那里写入可能会以任何你能想象的方式影响程序的行为。

如果你想要安全,你可以使用std::vector ,并且只能使用它的at()函数访问它的元素。 这将检查索引,如果超出范围则抛出exception。 它也将为你pipe理内存分配,修正你的例子中的内存泄漏。

具有良好代码分析的编译器肯定会警告那些超出数组分配的代码引用。 忘记多个声明,如果你运行它,它可能会或可能不会错误(未定义的行为,如别人所说)。 例如,如果你有一堆4KB的页面(在处理器地址空间中),如果你不在该页面之外写入,那么你将不会从处理器得到错误。 在删除数组时,如果你已经完成了这个操作,并且根据堆的实现,堆可能会检测到它已经损坏。