9

是否有任何提示/技巧来查找 shared_ptr 的循环引用?

这是我试图找到的一个例子 - 不幸的是,我似乎无法在我的代码中找到循环。

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

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

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

6 回答 6

5

我建议使用Valgrind。当您关闭该进程时,它会显示所有泄漏的内存。除非您的关闭以某种方式破坏了循环,否则任何循环都应该显示为泄漏的内存,并且 Valgrind 会告诉您代码中最初分配内存的位置。

于 2010-01-05T02:19:46.947 回答
3

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.

于 2010-01-05T00:56:02.967 回答
1

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.

于 2010-01-05T00:51:52.240 回答
1

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.

于 2010-02-02T23:10:15.597 回答
0

您可以实现某种调试接口,该接口返回此对象拥有的 shared_ptrs 列表。您需要对存储在 shared_ptr 中的每个类执行此操作。现在您有了一个可以遍历的通用图,并且可以在其上使用循环检测算法。我相信Tarjan 的强连通分量算法可能适用于此,但图论不是我的强项。

于 2010-01-05T11:28:18.290 回答
0

我想最简单的答案是只有这么多智能指针可以为你做:

我建议您在创建循环时进行记录(如果您同时创建所有三个对象很容易,否则会更棘手......),然后检查您删除/取消链接对象的记录,或者如果不可能,请定期检查。

于 2010-01-05T01:15:14.520 回答