简体   繁体   English

查找boost :: shared_ptr循环引用

[英]Finding boost::shared_ptr cyclic references

Is there any tips/tricks for finding cyclic references of shared_ptr's? 有没有找到shared_ptr的循环引用的提示/技巧?

This is an exmaple of what I'm trying to find - unfortunately I can't seem to find the loop in my code. 这是我想要找到的例子 - 不幸的是我似乎无法在我的代码中找到循环。

struct A
{
  boost::shared_ptr<C> anC;
};

struct B
{
  boost::shared_ptr<A> anA;
};

struct C
{
  boost::shared_ptr<B> anB;
};

I'd recommend using Valgrind . 我推荐使用Valgrind When you shut down the process, it will show you all leaked memory. 关闭进程时,它会显示所有泄漏的内存。 Unless your shutdown somehow breaks the cycle, any cycles should show up as leaked memory and Valgrind will tell you where in your code the memory was originally allocated from. 除非你的关闭以某种方式打破循环,否则任何循环都应该显示为泄漏的内存,Valgrind会告诉你代码中最初分配内存的位置。

I was in charge of the design of a credit risk system once (in C++, though that isn't relevant). 我曾负责信用风险系统的设计(在C ++中,虽然这不相关)。 These things are really big graphs with risk allocated at the nodes. 这些东西实际上是在节点上分配风险的大图。 We had a simple heuristic to find if we were in a cycle - if we traversed more than 500 times (I forget the exact figure - it was configurable), the answer was yes. 我们有一个简单的启发式方法来查找我们是否在一个循环中 - 如果我们遍历超过500次(我忘记了确切的数字 - 它是可配置的),答案是肯定的。 Most cycle detection schemes rely on heuristics like this. 大多数循环检测方案都依赖于这样的启发式方法。

I've had similar problems in the past - memory leaks due to shared_ptr cyclic references that went undetected for months. 我在过去遇到过类似的问题 - 由于shared_ptr循环引用导致内存泄漏几个月未被发现。

Watch out for "caches". 注意“缓存”。 I have an object (let's call it "Factory") which handled out items ("Widget"). 我有一个对象(让我们称之为“工厂”)来处理项目(“Widget”)。 Widgets had the property of being A) Immutable, and B) Had a shared_ptr<Factory> to its creator (it sometimes created other widgets, etc). 小部件具有A)不可变的属性,并且B)有一个shared_ptr<Factory>给它的创建者(它有时会创建其他小部件等)。 Everything worked fine, until I added a Widget cache to Factory - since the Widgets were immutable, it made sense to cache them, to hand back the same Widget everytime it was requested. 一切正常,直到我向工厂添加了一个Widget缓存 - 因为Widgets是不可变的,所以缓存它们是有意义的,每次请求时都要回传相同的Widget。 My cache was a cache of shared_ptr<Widget> , so instant silent leak. 我的缓存是shared_ptr<Widget>的缓存,因此即时无声泄漏。 The fixes are obvious, so I won't go into them. 修复是显而易见的,所以我不会进入它们。

Ultimately I was able to lean on the platform I was using to detect such memory leaks from the CRT. 最终,我能够依靠我用来检测CRT内存泄漏的平台。 Visual Studio's CRT has memory leaked detection and reporting, which I enabled in my test program to prevent regressions: Visual Studio的CRT具有内存泄漏检测和报告功能,我在测试程序中启用了该功能以防止回归:

int main()
{
    // code code code
    // code code code

#ifdef _MSC_VER
    _CrtSetReportMode( _CRT_WARN, _CRTDBG_MODE_FILE );
    _CrtSetReportFile( _CRT_WARN, _CRTDBG_FILE_STDOUT );
    _CrtSetReportMode( _CRT_ERROR, _CRTDBG_MODE_FILE );
    _CrtSetReportFile( _CRT_ERROR, _CRTDBG_FILE_STDOUT );
    _CrtSetReportMode( _CRT_ASSERT, _CRTDBG_MODE_FILE );
    _CrtSetReportFile( _CRT_ASSERT, _CRTDBG_FILE_STDOUT );
    _CrtDumpMemoryLeaks();
#endif
}

GCC probably has similar basic leak reporting, but I don't know what it is. GCC可能有类似的基本泄漏报告,但我不知道它是什么。

I used a combination of the above posts. 我使用了上述帖子的组合。 I used a memory profiler, came up with some suspected cycles and broke those by using weak_ptr's. 我使用了一个内存分析器,想出了一些可疑的循环,并通过使用weak_ptr来破坏它们。

I've used the built in CRT memory leak detection before, but unfortunately in my case there are several static singletons that dont get deallocated until module unload which I believe is after the CRT detectors lifecycle. 我之前使用过内置的CRT内存泄漏检测,但不幸的是在我的情况下有几个静态单例在模块卸载之前不会被释放,我认为这是在CRT探测器生命周期之后。 Basically it gives alot of spew that are false positives. 基本上它会给出大量的误报。

I guess the simplest answer is that there is only so much smart pointers can do for you: 我想最简单的答案是,只有这么多智能指针可以为你做:

I suggest recording whenever you make a loop, (easy if you create all three objects at once, trickier otherwise...), and then check that record where you delete / unlink objects, or just periodically if that is not possible. 我建议你一个循环时记录,(如果你一次创建所有三个对象就很容易,否则很难......),然后检查你删除/取消链接对象的记录,或者只是在不可能的情况下定期检查。

You could implement some sort of debugging interface that returns a list of shared_ptrs owned by this object. 您可以实现某种调试接口,该接口返回此对象拥有的shared_ptrs列表。 You'd need to do this for every class stored in a shared_ptr. 您需要为存储在shared_ptr中的每个类执行此操作。 Now you have a generic graph which you can traverse, and can use cycle detection algorithms on it. 现在您有了一个可以遍历的通用图,并且可以在其上使用循环检测算法。 I believe Tarjan's strongly connected component algorithm might work for this but graph theory is not my forté. 我相信Tarjan的强连通组件算法可能适用于此,但图论不是我的强项。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM