C ++在不知道大小的情况下检测悬空指针

时间:2012-08-03 12:13:17

标签: c++ arrays pointers null

考虑一段代码

int main(int argc,char* argv[]){
        int *arrPtr = new int[4];
        for (int i=0;i<4;i++)
                arrPtr[i]=i*2;


        for (int i=0;i<10;i++){
                arrPtr++;
                cout<<"arrPtr ["<<i<<"]\t"<<*arrPtr<<endl;
        }
        cout<<endl;
        return 0; }

编译此程序时

  

g ++ main.cpp -o main&amp;&amp; ./main

它给了我

arrPtr [0]  2
arrPtr [1]  4
arrPtr [2]  6
arrPtr [3]  0
arrPtr [4]  135145
arrPtr [5]  0
arrPtr [6]  0
arrPtr [7]  0
arrPtr [8]  0
arrPtr [9]  0

我希望能够在arrPtr未指向“valid”元素时检测(抛出或检查)。 在上面的代码中,最后一个有效元素是arrPtr [3]。

请不要“我太”回答!

4 个答案:

答案 0 :(得分:5)

使用vector

int main()
{
    std::vector<int> a(4);

    for (size_t i = 0; i < 4; ++i)
        a[i] = i * 2;
    for (size_t i = 0; i < 10; ++i)
        std::cout << i << ": " << a.at(i) << std::endl;
}

结果:

0: 0
1: 2
2: 4
3: 6
terminate called after throwing an instance of 'std::out_of_range'
  what():  vector::_M_range_check
Aborted

答案 1 :(得分:2)

其他人已经为这个具体问题展示了解决方案:使用std::vector而不是原始指针(无论如何都要这样做!)和通过.at()进行元素访问。

但是,一般来说,您应该确保代码中不会出现这种情况。超出范围的错误不是您应该在运行时处理的情况,它们在您的代码中是错误,需要事先删除。

有几种策略 - 例如,不要使用索引访问。大多数此类实例可以由迭代器访问替换,虽然它不是自动安全的,但却使得更难发生错误。

更好的是,尽可能避免使用循环,而是使用C ++标准库中的高阶算法。

作为一个例子,无循环代码可能是什么样的:

std::vector<int> arr;
std::generate_n(std::back_inserter(arr), 4,
    [] {
        static int current = 0;
        return current++ * 2;
    });
std::copy(begin(arr), end(arr), std::ostream_iterator<int>(std::cout, "\n"));

这种风格需要一些时间来习惯,但它大大减少了在代码中出错的机会,并使一些错误类不可能成为一个专家。

答案 2 :(得分:1)

使用普通的C阵列是不可能的。您可以使用std :: vector,它具有用于元素访问的API和边界检查。

答案 3 :(得分:0)

该主题已被广泛讨论。通常,在C语言中,不可能在不事先知道阵列的某些信息的情况下检测指针是否指向阵列中的位置。

正如@Charlie Martin在回答this post时提到的那样,这是因为边界检查会花费额外的操作。由于C通常用于制作对速度敏感的程序(例如硬件驱动程序),因此边界检查不是用语言实现的,而是由自己需要的人实现的。

因此,如果您想进行边界检查,您必须执行以下操作:

int *start = new int[4];
int size=4;
int *arrPtr;
...
for (int i=0,arrPtr=start;i<10;i++){
    arrPtr++;
    if(arrPtr>=start && arrPtr <start+size) // the boundary checking by yourself
       cout<<"arrPtr ["<<i<<"]\t"<<*arrPtr<<endl;
}

通过这种方式,语言可以让您决定使用附加操作进行边界检查是否值得和必要。

当然,一旦您确定需要在程序中进行边界检查,就已经实现了更高级别的数据类型,例如vector