是否有任何提示/技巧来查找 shared_ptr 的循环引用?
这是我试图找到的一个例子 - 不幸的是,我似乎无法在我的代码中找到循环。
struct A
{
boost::shared_ptr<C> anC;
};
struct B
{
boost::shared_ptr<A> anA;
};
struct C
{
boost::shared_ptr<B> anB;
};
是否有任何提示/技巧来查找 shared_ptr 的循环引用?
这是我试图找到的一个例子 - 不幸的是,我似乎无法在我的代码中找到循环。
struct A
{
boost::shared_ptr<C> anC;
};
struct B
{
boost::shared_ptr<A> anA;
};
struct C
{
boost::shared_ptr<B> anB;
};
我建议使用Valgrind。当您关闭该进程时,它会显示所有泄漏的内存。除非您的关闭以某种方式破坏了循环,否则任何循环都应该显示为泄漏的内存,并且 Valgrind 会告诉您代码中最初分配内存的位置。
I was in charge of the design of a credit risk system once (in C++, though that isn't relevant). 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. 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.
Watch out for "caches". I have an object (let's call it "Factory") which handled out items ("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). 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. My cache was a cache of shared_ptr<Widget>
, so instant silent leak. 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. Visual Studio's CRT has memory leaked detection and reporting, which I enabled in my test program to prevent regressions:
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.
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.
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. Basically it gives alot of spew that are false positives.
您可以实现某种调试接口,该接口返回此对象拥有的 shared_ptrs 列表。您需要对存储在 shared_ptr 中的每个类执行此操作。现在您有了一个可以遍历的通用图,并且可以在其上使用循环检测算法。我相信Tarjan 的强连通分量算法可能适用于此,但图论不是我的强项。
我想最简单的答案是只有这么多智能指针可以为你做:
我建议您在创建循环时进行记录(如果您同时创建所有三个对象很容易,否则会更棘手......),然后检查您删除/取消链接对象的记录,或者如果不可能,请定期检查。