有没有找到shared_ptr的循环引用的提示/技巧?
这是我想要找到的例子 - 不幸的是我似乎无法在我的代码中找到循环。
struct A
{
boost::shared_ptr<C> anC;
};
struct B
{
boost::shared_ptr<A> anA;
};
struct C
{
boost::shared_ptr<B> anB;
};
答案 0 :(得分:5)
我建议使用Valgrind。关闭进程时,它会显示所有泄漏的内存。除非你的关闭以某种方式打破循环,否则任何循环都应该显示为泄漏的内存,Valgrind会告诉你代码中最初分配内存的位置。
答案 1 :(得分:3)
我曾经负责信用风险系统的设计(在C ++中,虽然这不相关)。这些东西实际上是在节点上分配风险的大图。我们有一个简单的启发式方法来查找我们是否在一个循环中 - 如果我们遍历超过500次(我忘记了确切的数字 - 它是可配置的),答案是肯定的。大多数循环检测方案都依赖于这样的启发式方法。
答案 2 :(得分:1)
过去我遇到过类似的问题 - 由于shared_ptr循环引用造成的内存泄漏几个月未被发现。
注意“缓存”。我有一个对象(让我们称之为“工厂”)来处理项目(“Widget”)。小部件具有A)不可变的属性,并且B)对其创建者有shared_ptr<Factory>
(它有时创建其他小部件等)。一切正常,直到我向工厂添加了一个Widget缓存 - 因为Widgets是不可变的,所以缓存它们是有意义的,每次请求时都要回传相同的Widget。我的缓存是shared_ptr<Widget>
的缓存,所以即时无声泄漏。修复是显而易见的,所以我不会进入它们。
最终,我能够依靠我用来检测CRT内存泄漏的平台。 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可能有类似的基本泄漏报告,但我不知道它是什么。
答案 3 :(得分:1)
我使用了上述帖子的组合。我使用了一个内存分析器,想出了一些可疑的循环,并使用weak_ptr来破坏它们。
之前我使用过内置的CRT内存泄漏检测,但不幸的是在我的情况下有几个静态单例在模块卸载之前不会被释放,我认为这是在CRT探测器生命周期之后。基本上它会产生很多误报。
答案 4 :(得分:0)
我想最简单的答案是,只有这么多智能指针可以为你做到:
我建议您在制作循环时进行录制(如果您一次创建所有三个对象,则很容易,否则很难......),然后检查删除/取消链接对象的记录,或者如果不可能的话,只是定期。
答案 5 :(得分:0)
您可以实现某种调试接口,该接口返回此对象拥有的shared_ptrs列表。您需要为存储在shared_ptr中的每个类执行此操作。现在您有了一个可以遍历的通用图,并且可以在其上使用循环检测算法。我相信Tarjan's strongly connected component algorithm可能对此有用,但图论不是我的强项。