我在C ++的应用程序中使用boost :: shared_ptr。内存问题非常严重,应用程序占用大量内存。
但是,因为我将每个新建对象放入shared_ptr,当应用程序退出时,不会检测到内存泄漏。
必须有一些像std::vector<shared_ptr<> >
池这样的东西来保存资源。调试时如何知道谁拥有shared_ptr?
很难逐行检查代码。代码太多......
非常感谢!
答案 0 :(得分:21)
你只能通过查看“兄弟指针”所在的shared_ptr
来了解。您可以在other methods中测试一个是unique()
还是use_count()
。
答案 1 :(得分:12)
shared_ptr的广泛使用几乎不可避免地会导致不必要的和看不见的内存占用。
循环引用是一个众所周知的原因,其中一些可能是间接的,很难发现,特别是在由多个程序员处理的复杂代码中;程序员可能决定一个对象需要引用另一个对象作为快速修复,并且没有时间检查所有代码以查看他是否正在关闭一个循环。这种危险被严重低估了。
不太清楚的是未发布的引用问题。如果一个对象被共享给许多shared_ptrs,那么在它们中的每一个被归零或超出范围之前它都不会被销毁。很容易忽略其中一个引用,并最终得到你认为已经完成的内存中看不见的对象。
虽然严格来说这些不是内存泄漏(它会在程序退出之前全部释放)但它们同样有害且难以检测。
这些问题是权宜的虚假声明的后果: 1.声明你真正希望成为shared_ptr的单一所有权。 scoped_ptr是正确的,但是对该对象的任何其他引用都必须是一个原始指针,可以留下悬空。 2.声明你真正想要成为被动观察引用的是shared_ptr。 weak_ptr是正确的,但是每次你想要使用它时,你都有把它转换成share_ptr的麻烦。
我怀疑你的项目是这种做法可以帮助你解决的一个很好的例子。
如果你有一个内存密集型应用程序,你真的需要单一所有权,这样你的设计就可以明确地控制对象的生命周期。
单一所有权opObject = NULL;肯定会删除该对象,现在就可以了。
使用共享所有权spObject = NULL; ........谁知道?......
答案 2 :(得分:7)
我们所做的悬空或循环智能指针引用的一个解决方案是自定义智能指针类以添加仅调试的簿记功能。每当一个智能指针添加一个对象的引用时,它会采用堆栈跟踪并将其放入一个地图中,每个条目都跟踪
当智能指针超出范围时,其在地图中的条目将被删除。当对象的最后一个智能指针被销毁时,指针对象会在地图中删除它的条目。
然后我们有一个带有两个功能的“track leaks”命令:'[re]启动泄漏跟踪'(清除整个地图并启用跟踪,如果还没有),'print open references',显示所有优秀自“启动泄漏跟踪”命令发出以来创建的智能指针引用。由于您可以看到这些智能指针所在的堆栈跟踪,因此您可以轻松地确切知道谁将保留您的对象。当它开启时它会减慢速度,所以我们不会一直保持开启状态。
实施这项工作是相当多的工作,但如果你有一个代码库,那么它肯定是值得的。
答案 3 :(得分:3)
您可能通过循环遇到共享指针内存泄漏。发生的事情是您的共享对象可能包含对其他共享对象的引用,这些对象最终会返回原始对象。发生这种情况时,即使没有其他人可以访问对象,循环也会将所有引用计数保持为1。解决方案是weak pointers。
答案 4 :(得分:3)
尝试重构一些代码,以便通过在某些地方使用弱指针而不是共享指针来更明确地表达所有权。
当查看你的类层次结构时,可以确定哪个类确实应该保存共享指针,哪个只需要弱指针,所以你可以避免循环,如果有的话,如果“真正的”所有者对象被破坏, “非所有者”对象应该已经消失了。如果事实证明某些对象过早丢失指针,则必须在应用程序中查看对象销毁序列并进行修复。
答案 5 :(得分:1)
您显然在应用程序中持有对象的引用。这意味着您有意将事物记忆在内。这意味着,您没有内存泄漏。内存泄漏是在分配内存时,然后您不保留对其地址的引用。
基本上,您需要查看您的设计,找出为什么要在内存中保留如此多的对象和数据,以及如何将其最小化。
你有一个伪内存泄漏的可能性是你创建的对象比你想象的要多。尝试在包含'new'的所有语句上添加断点。查看您的应用程序是否构建了比您想象的更多的对象,然后阅读该代码。
问题实际上不是内存泄漏,而是因为它是应用程序设计的问题。
答案 6 :(得分:1)
如果你在Windows上,我打算建议使用UMDH。这是一个非常强大的工具。使用它查找您希望被释放的每个事务/时间段的分配,然后查找持有它们的人。
有关此SO答案的更多信息 Find memory leaks caused by smart pointers
答案 7 :(得分:-1)
无法从程序中分辨出哪些对象拥有shared_ptr。如果您使用的是Linux,那么调试内存泄漏的一种可靠方法是Valgrind工具 - 虽然它不会直接回答您的问题,但它会告诉内存的分配位置,这通常足以修复问题。我认为Windows有类似的工具,但我不知道哪一个最好。