调试.NET内存泄漏 - 如何知道什么是什么?

Dr.*_*ABT 7 c# garbage-collection memory-leaks

我正在开发一个似乎存在内存泄漏的.NET应用程序.我知道教科书的答案,事件应该取消订阅,一次性物品应该处理等...

我有一个可以重现错误的测试工具.在某个类的终结器中,我写入控制台

public class Foo
{
   // Ctor
   public Foo()
   {
   }

   ~public Foo()
   {
       Console.WriteLine("Foo Finalized");
   }
}
Run Code Online (Sandbox Code Playgroud)

在测试工具中,我创建了一个Foo实例(它反过来创建并与数百种其他类型交互)然后删除它并调用垃圾收集器.

我发现从未调用过Foo Finalizer.我有一个类似的类与此设置,最终确定为控制测试.

所以我的问题是:

我怎样才能确定使用商业或开源工具究竟是什么引用了Foo?

我拥有dotTrace Memory Profiler的专业许可,但无法从帮助文件中找出如何使用它.

更新:我现在使用dotMemory 4.0,它是(好的,但无法使用的)dotTrace Memory 3.5的继承者.

slo*_*oth 6

有一个SOS调试扩展(这是免费的,一个可以在Visual Studio中使用).

您可能会发现这一点,有助于获得startet.

如果你已经成功地设置了SOS(有时候这可能很棘手),知道什么是对简单的东西的引用

// load sos
.load sos
// list of all instances of YourTypeName in memory with their method tables
!DumpHeap -type YourTypeName  
// put here the method table displayed by the previous command
// it will show you the memory address of the object
!DumpHeap -mt 07f66b44              
// displays information about references the object at the specified address
!GCRoot 02d6ec94
Run Code Online (Sandbox Code Playgroud)


And*_*ren 3

终结器不是确定性调用的,因此请小心使用它以可靠的方式跟踪事物。如果您删除终结器并改为使用 a,WeakReference<Foo>您应该能够确定该对象是否已被收集。

所有内存分析器都应该能够发现此类问题,但难度各异。我个人使用过ANTS,它非常好用,但不是免费的。它将帮助您显示从 GC 根对象到 Foo 实例的参考图。看到此图通常很容易找出谁持有参考。