代码之家  ›  专栏  ›  技术社区  ›  Zac

查找boost::共享的循环引用

  •  9
  • Zac  · 技术社区  · 15 年前

    找到共享指针的循环引用有什么技巧吗?

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

    struct A
    {
      boost::shared_ptr<C> anC;
    };
    
    struct B
    {
      boost::shared_ptr<A> anA;
    };
    
    struct C
    {
      boost::shared_ptr<B> anB;
    };
    
    6 回复  |  直到 15 年前
        1
  •  5
  •   R Samuel Klatchko    15 年前

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

        2
  •  3
  •   anon    15 年前

    我曾经负责信用风险系统的设计(在C++中,虽然这不相关)。这些都是在节点上分配风险的非常大的图。我们有一个简单的启发式方法来确定我们是否在一个循环中——如果我们遍历了500次以上(我忘记了确切的数字——它是可配置的),答案是肯定的。大多数周期检测方案都依赖这样的启发式方法。

        3
  •  1
  •   Terry Mahaffey    15 年前

    我在过去也遇到过类似的问题——内存泄漏是由于共享的循环引用几个月没有被检测到。

    当心“缓存”。我有一个对象(我们称之为“工厂”),它处理了项目(“小部件”)。小部件具有a)不可变的特性,b)具有 shared_ptr<Factory> 对它的创建者(它有时创建其他小部件等)。一切都很好,直到我在工厂添加了一个小部件缓存——因为小部件是不可变的,所以缓存它们,在每次请求时都将相同的小部件交回是有意义的。我的缓存是 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可能有类似的基本泄漏报告,但我不知道它是什么。

        4
  •  1
  •   Zac    15 年前

    我把上面的文章结合起来。我使用了一个内存分析器,提出了一些可疑的循环,并使用弱指针来打破这些循环。

    我以前使用过内置的CRT内存泄漏检测,但不幸的是,在我的例子中,有几个静态单例在模块卸载之前无法释放,我认为这是在CRT探测器的生命周期之后。基本上,它给出了大量的误报。

        5
  •  0
  •   James    15 年前

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

    我建议你什么时候录音 制作 一个循环(如果一次创建所有三个对象很简单,否则更复杂),然后检查删除/取消链接对象的记录,如果不可能,则定期检查。

        6
  •  0
  •   Kylotan    15 年前

    您可以实现某种调试接口,返回此对象拥有的共享指针列表。对于存储在共享资源中的每个类,都需要这样做。现在您有了一个可以遍历的通用图,并且可以在上面使用循环检测算法。我相信 Tarjan's strongly connected component algorithm 也许可以,但图论不是我的堡垒。