13

我在 C++ 的应用程序中使用 boost::shared_ptr。内存问题真的很严重,应用程序占用大量内存。

但是,因为我将每个新对象都放入了一个 shared_ptr,所以当应用程序退出时,无法检测到内存泄漏。

必须有一些东西,比如std::vector<shared_ptr<> >持有资源的池。调试时如何知道谁拥有 shared_ptr?

很难逐行查看代码。代码太多...

非常感谢!

4

8 回答 8

22

仅通过查看 a ,您无法知道shared_ptr“兄弟指针”在哪里。您可以测试一个是否是unique()或获取use_count(),以及其他方法

于 2009-06-30T04:03:10.193 回答
12

shared_ptr 的流行广泛使用几乎不可避免地会导致不必要的和看不见的内存占用。

循环引用是一个众所周知的原因,其中一些可能是间接的并且难以发现,尤其是在由多个程序员编写的复杂代码中;程序员可能决定一个对象需要引用另一个对象作为快速修复,并且没有时间检查所有代码以查看他是否正在关闭一个循环。这种危险被大大低估了。

不太为人所知的是未发布参考的问题。如果一个对象被共享给许多 shared_ptrs,那么它不会被销毁,直到它们中的每一个都归零或超出范围。很容易忽略其中一个引用,并最终得到潜伏在内存中看不见的对象,而你认为​​你已经完成了。

虽然严格来说这些不是内存泄漏(它会在程序退出之前全部释放),但它们同样有害且更难检测。

这些问题是权宜之计错误声明的后果: 1. 将您真正想要的单一所有权声明为 shared_ptr。scoped_ptr 是正确的,但是对该对象的任何其他引用都必须是原始指针,它可能会悬空。2. 将你真正想要的被动观察引用声明为 shared_ptr。weak_ptr 是正确的,但是每次你想使用它时,你都会很麻烦地将它转换为 share_ptr。

我怀疑你的项目是这种做法会给你带来的麻烦的一个很好的例子。

如果您有一个内存密集型应用程序,您确实需要单一所有权,以便您的设计可以明确控制对象的生命周期。

单一所有权 opObject=NULL; 肯定会删除该对象,它现在会这样做。

共享所有权 spObject=NULL; ........谁知道?......

于 2009-08-07T08:15:53.767 回答
7

我们已经完成的悬空或循环智能指针引用的一种解决方案是自定义智能指针类以添加仅用于调试的簿记功能。每当智能指针添加对对象的引用时,它都会获取堆栈跟踪并将其放入每个条目跟踪的映射中

  1. 正在分配的对象的地址(指针指向的内容)
  2. 持有对该对象的引用的每个智能指针对象的地址
  3. 构造每个智能指针时的相应堆栈跟踪

当智能指针超出范围时,它在映射中的条目将被删除。当一个对象的最后一个智能指针被销毁时,被指针对象将其在映射中的条目删除。

然后我们有一个“跟踪泄漏”命令,它有两个功能:“[重新]开始泄漏跟踪”(清除整个地图并启用跟踪,如果还没有)和“打印打开的引用”,它显示创建的所有未完成的智能指针引用因为发出了“开始泄漏跟踪”命令。由于您可以看到这些智能指针出现的位置的堆栈跟踪,因此您可以轻松地准确知道谁在阻止您的对象被释放。它打开时会减慢速度,因此我们不会一直打开它。

这是相当多的工作来实现,但如果你有一个经常发生这种情况的代码库,那绝对值得。

于 2013-02-28T09:22:38.873 回答
4

您可能会通过循环遇到共享指针内存泄漏。发生的情况是您的共享对象可能持有对其他共享对象的引用,这些引用最终会回到原始对象。发生这种情况时,即使没有其他人可以访问对象,循环也会将所有引用计数保持为 1。解决方案是弱指针

于 2009-06-30T05:16:26.647 回答
3

尝试重构您的一些代码,以便通过在某些地方使用弱指针而不是共享指针来更明确地表达所有权。

在查看您的类层次结构时,可以确定哪个类真正应该拥有一个共享指针,而哪个只需要弱指针,因此您可以避免循环(如果有的话)并且如果“真正的”所有者对象被破坏,“非-所有者”对象应该已经消失了。如果事实证明某些对象过早丢失指针,您必须查看应用程序中的对象销毁顺序并修复它。

于 2009-06-30T05:54:10.217 回答
1

您显然在应用程序中保留对对象的引用。这意味着您是故意将事情记在内存中的。这意味着,您没有内存泄漏。内存泄漏是在分配内存时,然后您没有保留对其地址的引用。

基本上,您需要查看您的设计并弄清楚为什么要在内存中保留如此多的对象和数据,以及如何将其最小化。

您有伪内存泄漏的一种可能性是您创建的对象比您想象的要多。尝试在所有包含“新”的语句上放置断点。查看您的应用程序构建的对象是否比您想象的要多,然后通读该代码。

问题实际上与其说是内存泄漏,不如说是应用程序设计的问题。

于 2009-06-30T04:02:03.283 回答
1

如果您在 Windows 上,我将建议使用 UMDH。这是一个非常强大的工具。使用它查找您希望被释放的每个事务/时间段的分配,然后找到谁持有它们。

有关此 SO 答案的更多信息 查找由智能指针引起的内存泄漏

于 2009-08-07T09:29:29.407 回答
0

无法从程序中分辨出哪些对象拥有 shared_ptr。如果您在 Linux 上,调试内存泄漏的一种可靠方法是Valgrind工具——虽然它不会直接回答您的问题,但它会告诉您分配内存的位置,这通常足以解决问题。我想 Windows 有类似的工具,但我不知道哪个是最好的。

于 2009-07-01T06:54:25.087 回答