我在一个c++程序中分配值,就像这样:

#include <iostream>
using namespace std;
int main()
{
    int array[2];
    array[0] = 1;
    array[1] = 2;
    array[3] = 3;
    array[4] = 4;
    cout << array[3] << endl;
    cout << array[4] << endl;
    return 0;
}

程序输出3和4。这应该是不可能的。我使用g++ 4.3.3

下面是编译和运行命令

$ g++ -W -Wall errorRange.cpp -o errorRange
$ ./errorRange
3
4

只有当分配数组[3000]=3000时,它才会给我一个分割错误。

如果gcc不检查数组边界,我怎么能确定我的程序是正确的,因为它可能导致一些严重的问题以后?

我将上面的代码替换为

vector<int> vint(2);
vint[0] = 0;
vint[1] = 1;
vint[2] = 2;
vint[5] = 5;
cout << vint[2] << endl;
cout << vint[5] << endl;

这个也不会产生误差。


当前回答

使用g++,可以添加命令行选项:-fstack-protect -all。

在你的例子中,结果如下:

> g++ -o t -fstack-protector-all t.cc
> ./t
3
4
/bin/bash: line 1: 15450 Segmentation fault      ./t

它并不能真正帮助您找到或解决问题,但至少段错误会让您知道有什么地方出错了。

其他回答

当你用int array[2]初始化数组时,为2个整数分配空间;但是标识符数组只是指向该空间的开始。当你访问数组[3]和数组[4]时,如果数组足够长,编译器会简单地增加地址以指向这些值的位置;尝试访问像数组[42]这样的东西,而不首先初始化它,您将最终获得内存中该位置已经存在的任何值。

编辑:

关于指针/数组的更多信息:http://home.netcom.com/~tjensen/ptr/pointers.htm

正如现在在问题中提到的,使用std::vector::at将解决问题,并在访问前进行绑定检查。

如果你需要一个位于堆栈上的常量大小数组作为你的第一个代码,请使用c++ 11新容器std::array;作为向量,有std::array::at函数。事实上,这个函数存在于所有有意义的标准容器中。E,其中操作符[]被定义为:(deque, map, unordered_map),除了std::bitset,其中它被称为std::bitset::test。

不明确的行为对你有利。不管你要破坏的是什么内存,显然都没有任何重要的东西。注意,C和c++不对数组进行边界检查,因此在编译或运行时不会捕获类似的东西。

The behavior can depend on your system. Typically, you will have a margin for out of bounds, sometimes with value of 0 or garbage values. For the details you can check with memory allocation mechanism used in your OS. On top of that, if you use the programming language like c/c++, it will not check the bounds when you using some containers, like array. So, you will meet "undefined event" because you do not know what the OS did below the surface. But like the programming language Java, it will check the bound. If you step outside of the bound, you will get an exception.

据我所知,局部变量是在堆栈上分配的,所以在你自己的堆栈上越界只能覆盖一些其他的局部变量,除非你oob太多,超过了你的堆栈大小。 由于在函数中没有声明其他变量,因此不会产生任何副作用。尝试在第一个变量/数组之后声明另一个变量/数组,看看会发生什么。