我在一个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;

这个也不会产生误差。


当前回答

libstdc++是gcc的一部分,它有一个用于错误检查的特殊调试模式。它由编译器标志-D_GLIBCXX_DEBUG启用。其中,它以性能为代价对std::vector进行边界检查。这是gcc最新版本的在线演示。

因此,实际上您可以使用libstdc++调试模式进行边界检查,但您应该只在测试时执行,因为与正常的libstdc++模式相比,它的性能损失显著。

其他回答

libstdc++是gcc的一部分,它有一个用于错误检查的特殊调试模式。它由编译器标志-D_GLIBCXX_DEBUG启用。其中,它以性能为代价对std::vector进行边界检查。这是gcc最新版本的在线演示。

因此,实际上您可以使用libstdc++调试模式进行边界检查,但您应该只在测试时执行,因为与正常的libstdc++模式相比,它的性能损失显著。

Hint

如果你想要快速约束大小数组的范围错误检查,尝试使用boost::array,(也std::tr1::array from <tr1/array>,它将是下一个c++规范的标准容器)。它比std::vector快得多。它在堆上或类实例内部保留内存,就像int array[]一样。 这是一个简单的示例代码:

#include <iostream>
#include <boost/array.hpp>
int main()
{
    boost::array<int,2> array;
    array.at(0) = 1; // checking index is inside range
    array[1] = 2;    // no error check, as fast as int array[2];
    try
    {
       // index is inside range
       std::cout << "array.at(0) = " << array.at(0) << std::endl;

       // index is outside range, throwing exception
       std::cout << "array.at(2) = " << array.at(2) << std::endl; 

       // never comes here
       std::cout << "array.at(1) = " << array.at(1) << std::endl;  
    }
    catch(const std::out_of_range& r)
    {
        std::cout << "Something goes wrong: " << r.what() << std::endl;
    }
    return 0;
}

这个程序将打印:

array.at(0) = 1
Something goes wrong: array<>: index out of range

当然,您正在重写堆栈,但是程序非常简单,因此不会注意到这种影响。

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

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

C或c++不会检查数组访问的边界。

您正在堆栈上分配数组。通过数组[3]索引数组等价于*(array + 3),其中array是指向&array[0]的指针。这将导致未定义的行为。

在C语言中捕捉这种情况的一种方法是使用静态检查器,例如splint。如果你运行:

splint +bounds array.c

on,

int main(void)
{
    int array[1];

    array[1] = 1;

    return 0;
}

然后你会得到警告:

数组.c:(在函数main中) array.c:5:9:可能超出范围 存储: 数组[1] 无法解决约束的: 要求0 >= 1 需要满足的先决条件: require maxSet(array @ array.c:5:9) >= 1 地址以外的地址 分配的缓冲区。