代码之家  ›  专栏  ›  技术社区  ›  Paul Stovell

获取对对象的活动引用

  •  4
  • Paul Stovell  · 技术社区  · 15 年前

    我正在寻找一个托管/非托管API,它允许我查找哪些对象引用了另一个对象,并可能阻止它被垃圾收集。

    这样的API可能如下所示:

    var foo = new Foo();
    var bar = new Bar();
    bar.Foo = foo;
    
    var references = GC.GetReferencesTo(foo);
    // references is an array that contains bar
    

    我知道profiler可以用于此目的,但我想将其作为单元测试的一部分。我是否可以使用托管或非托管API?

    3 回复  |  直到 15 年前
        1
  •  5
  •   ShuggyCoUk    15 年前

    非托管的dll-sos(strike之子)提供了实现这一点的方法,尽管我认为它不具有重要的脚本支持,也不提供通过单个命令实现这一点的简单方法。您必须反省变量的地址,检查变量的所有gcrots(显然包括堆栈),并处理其余部分。

    我建议,如果你想证明一个物体 引用,一个更简单的技术是(暂时)使其可完成,确保不再在单元测试的堆栈上引用它,然后通过 GC.Collect() 然后使用 GC.WaitForPendingFinalizers() .

    Finalize方法可以设置静态布尔标志,然后单元测试可以断言这是真的。

    我会质疑 效用 对此,没有进一步的解释,但这可能是证明单元测试中不存在悬空引用的最简单方法。

        2
  •  3
  •   Pavel Minaev    15 年前

    .NET探查器使用 profiling API 跟踪对象的图形。您可能对回调方法特别感兴趣 ObjectReferences RootReferences 可能还有 ObjectAllocated . 在每次垃圾收集之后,将调用前两个方法来覆盖整个活动对象图,因此仅截取它们就足以重建该图,然后以您想要的任何方式对其进行分析。

    This article 解释如何将所有部件组合在一起。

        3
  •  1
  •   John K    15 年前

    还要记住.NET的用法 traced garbage collection 因此,如果你的应用不再引用任何对象,其他对象引用的对象(例如对象图)仍将被GC清除;它比.NET之前的经典引用计数垃圾收集算法聪明得多。这意味着,即使您找到了一种方法来精确定位对某个对象的所有引用,其中一些引用可能并不重要,也可能不需要处理。

    这并不能直接回答如何查找对象的所有引用,但会让读者意识到,当您通过工具或实用程序查找所有引用时,某些类型的东西不再需要在.NET中修复,例如经典的循环引用,因此您可能需要寻找一些巧妙的kn方法。在试图修复内存泄漏时忽略了什么。

    此说明仅适用于托管代码方案。