C# WPF 中的内存泄漏

27

我需要一些关于在C#中追踪内存泄漏原因的建议。我了解什么是内存泄漏,也明白为什么它们会在C#中发生,但我想知道您过去使用过哪些工具/策略来解决它们?

我正在使用.NET Memory Profiler,并发现我的一个巨大的主对象在我关闭它管理的窗口后仍保留在内存中,但我不知道该如何切断与它的所有链接。

如果我表述不够清楚,请发布一个带有问题的回答,我将根据回答编辑我的问题。谢谢!


另外,还可以尝试使用蚂蚁内存分析器,它能够显示指向给定对象的所有引用对象。 - Ian Ringrose
2个回答

39

进入调试器,然后在立即窗口中输入以下内容:

.load C:\Windows\Microsoft.NET\Framework\v2.0.50727\sos.dll

sos.dll的路径因系统而异。找到正确的路径的方法是在“模块”窗格中查找mscorwks.dll,该dll所在的位置即为sos.dll的正确路径。

然后输入以下内容:

System.GC.Collect()

这将确保收集任何不可达的内容。然后输入:

!DumpHeap -type <some-type-name>

这将向您显示包含地址的所有现有实例的表格。您可以通过以下方式找出是什么使一个实例保持活动状态:

!gcroot <some-address>

我不得不使用 System.GC.Collect() 来使垃圾回收工作。 - nash
我认为这可能取决于调试器在中断时停止的位置。我会修复我的答案,使其无论如何都能正常工作。 - Daniel Earwicker

8
.NET Memory Profiler是一款优秀的工具,我经常用它来诊断WPF应用程序中的内存泄漏问题。如您所知,使用该工具的好方法是在使用特定功能之前拍摄快照,然后在使用后、关闭窗口等操作后再拍摄第二个快照。比较两个快照时,您可以看到分配但未释放某种类型对象的数量:这就是内存泄漏。双击一个类型后,分析器将显示保持该类型对象存活的最短根路径。在WPF中,.NET对象可能以许多不同的方式泄漏,因此发布您正在看到的根路径应有助于确定根本原因。总的来说,尽量了解为什么这些对象会保留您的对象,并查看是否有一些方法可以在窗口关闭时分离事件处理程序、绑定等。

我最近发布了一篇 博客文章,讨论了由于特定绑定而引起的某些内存泄漏问题;对于这种特定类型的泄漏,那里的代码可以帮助找到有问题的绑定。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接