获取对象的活动引用

我正在寻找一个托管/非托管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 

我知道可以使用分析器,但我想将它作为unit testing的一部分。 我可以使用托管或非托管API吗?

非托管dll SOS(Son Of Strike)提供了一种实现这一目标的方法,虽然我不认为它具有重要的脚本支持,也没有提供通过单个命令实现此目的的简单方法。 你必须反省变量的地址,检查变量的所有gcroots(显然包括堆栈)并处理余数。

我建议,如果你想certificate一个对象没有被引用,一个更简单的技术是(暂时)使它可以完成,确保它不再被你的unit testing的堆栈引用然后通过强制几个垃圾收集GC.Collect()然后使用GC.WaitForPendingFinalizers() 。

你的finalize方法可以设置一个静态布尔标志,然后你的unit testing可以断言这是真的。

我会在没有进一步解释的情况下质疑它的实用性 ,但这可能是certificateunit testing中不存在悬空引用的最简单方法。

.NET Profiler使用分析API来跟踪对象图。 您可能对回调方法ObjectReferencesRootReferences特别感兴趣,也可能对ObjectAllocated 。 在每次垃圾收集之后,将调用前两个方法来覆盖整个活动对象图,因此单独拦截它们就足以重建该图,然后以您想要的任何方式对其进行分析。

本文将介绍如何将所有部分组合在一起。

还记得.NET使用跟踪垃圾收集,因此如果你的应用程序不再引用其中任何一个,那么GC仍将清理其他对象引用的对象 – 例如对象图 – ; 它比.NET之前的经典引用计数垃圾收集算法更加智能。 这意味着即使您找到一种方法来精确定位对象的所有引用,其中一些可能无关紧要,可能不需要处理。

这并没有直接回答如何找到对象的所有引用,但确实让读者意识到当你通过工具或实用程序找到所有引用时,某些事情不需要修复的情况。在.NET中更长 – 例如经典循环引用,因此您可能需要寻找一些巧妙的方法来了解在尝试修复内存泄漏时要忽略的内容。

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