-1

这个非常简单的代码演示了复杂环境中野指针导致的那种麻烦。

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.
}

有什么方法可以检测或预防问题?智能指针在这里有帮助吗?

4

6 回答 6

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.
于 2011-12-07T09:29:46.190 回答
2

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

您拥有的代码无效并且会导致未定义的行为,但无论如何 - C++ 在内存使用方面并不是很严格,这就是它的美妙之处(以及诅咒......)。有一些外部工具可以帮助检测泄漏(尽管不像您展示的那样),但它基本上归结为使用正确的构造和正确编程。C++ 提供了很大的灵活性,但如果使用不当 - 您会遇到令人讨厌的错误。

于 2011-12-07T09:20:59.480 回答
2

您可以使用(至少在 Linux 上)像valgrind这样的工具来追踪此类错误。

你也可以使用Boehm 的垃圾收集器(不用担心释放内存)。

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

阅读有关RAII的更多信息(这在 C++ 中很常见,但不是通用的口头禅:例如,好的 Ocaml 代码不要遵循它)。

你可以使用智能指针。

于 2011-12-07T09:22:02.807 回答
0

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

于 2011-12-07T09:22:19.643 回答
0
int *a2 = new int;
delete tmp;
//now, the a2 pointer may be a wild pointer

不,指针a2指向一个有效(未释放)的位置。

据我所知,没有这样的方法可以确定指针是否指向内存中的有效(非空闲)位置。

对于您的第一个示例,您可以使用 astd::shared_ptr对分配的内存位置的这种共享所有权进行建模。

于 2011-12-07T09:22:49.573 回答
0

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

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

valgrind等工具会覆盖该delete语句,并将内存标记为无效,以便后续访问可以被检测和报告。例如,很流行用0xDEADBEEF调试时突出的值覆盖这种应该被删除的内存,这样你很快就知道你正在访问一个已删除的内存区域。

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

于 2011-12-07T09:23:28.207 回答