如何检测或阻止野指针

时间:2011-12-07 09:18:32

标签: c++ pointers dangling-pointer

这个非常简单的代码演示了野生指针在复杂环境中造成的麻烦。

int main()
{
    int *a1 = new int;
    int *tmp = a1;
    delete a1;
    // Now, the tmp pointer is a wild pointer, it's dangerous.

    int *a2 = new int;
    delete tmp;
    // Now, the a2 pointer may be a wild pointer.
}

有没有办法检测或预防问题?聪明的指针在这里有帮助吗?

6 个答案:

答案 0 :(得分:2)

使用智能指针。为什么不呢?

你拥有的代码是无效的并且会导致未定义的行为,但无论如何 - 当涉及到内存使用时,C ++并不是非常严格,这就是它的美妙之处(以及诅咒......)。有一些外部工具可以帮助检测泄漏(虽然不是像你所示的情况),但它基本上归结为正确使用正确的结构和编程。 C ++允许很多灵活性,但如果不正确使用 - 你会得到令人讨厌的错误。

答案 1 :(得分:2)

你可以使用(至少在Linux上)像valgrind这样的工具来追逐这些错误。

你也可以使用Boehm's garbage collector(而不用担心释放内存)。

有些(IMHO设计糟糕的)类需要被删除(即因为它们在析构函数中做了重要的事情,除了释放内存)或者不应该有实例的手动指针。

阅读更多关于RAII的信息(这在C ++中非常常见,但不是一个普遍的口头禅:例如,好的Ocaml代码不会遵循它。)

你可以使用智能指针。

答案 2 :(得分:2)

这个问题的解决方案非常简单:

  

始终清楚代码中资源的所有权,并通过使用管理资源生命周期的类来强制执行此所有权。

在这种情况下,(假设你需要使用指针),我建议的生命周期如下:

//Limit the scope of the variables to the minimum required:
{
    //a1 owns the pointer, so make it a `unique_ptr`
    std::unique_ptr<int> a1(new int);
    //tmp does not own the pointer, so make it a raw pointer
    //limit its scope to a shorter scope than a1
    int *tmp = a1.get();
}
//now the tmp pointer does not exist. It cannot be dangerous

//A similar strategy applies here
{
    //a2 owns the pointer
    std::unique_ptr<int> a2(new int);
}
//Again, a2 goes out of scope before any damage can occur.

答案 3 :(得分:0)

唯一的方法是尽可能地对代码进行单元测试,使用valgrind等工具运行程序和单元测试,并希望能够捕获所有内存访问问题。

答案 4 :(得分:0)

int *a2 = new int;
delete tmp;
//now, the a2 pointer may be a wild pointer

不,指针a2指向有效(非自由)位置。

据我所知,没有办法确定指针是否指向内存中的有效(非自由)位置。

对于您的第一个示例,您可以使用std::shared_ptr在分配的内存位置为此共享所有权建模。

答案 5 :(得分:0)

使用C,没有人会阻止你将自己射入脚中。

有一些方法可以让自己更轻松,例如C ++智能指针:http://en.wikipedia.org/wiki/Smart_pointer#C.2B.2B_Smart_Pointers

诸如valgrind之类的工具将覆盖delete语句,并将内存标记为无效,以便可以检测并报告后续访问。例如,在调试时使用0xDEADBEEF这样的值来覆盖这种假定要删除的内存是很流行的,因此您很快就会知道您正在访问已删除的内存区域。

对于生产,您通常希望跳过写入不再需要的内存,因此这些内容只应在调试模式下启用。