【发布时间】:2016-06-25 08:08:33
【问题描述】:
我有一个相当大的 WinForms 应用程序,但我使用任务管理器检测到 USER 对象泄漏(和较小的 GDI 泄漏)。
应用程序运行后,我打开一个表单,其中显示从服务器组件检索到的一些数据(使用 WCF)。然后我关闭表格。出于测试目的,我正在运行垃圾收集。
然后我通过 USER 和 GDI 计数的任务管理器记下基本注释,并重复打开/关闭/收集多次。
在此过程中,我看到以下内容: USER / GDI 计数
824 / 347
830 / 349
835 / 349
867 / 361
872 / 361
876 / 361
908 / 371
940 / 381
945 / 381
977 / 391
现在考虑到我一直在执行相同的操作,我无法理解为什么 USER / GDI 增加是非线性的。如果一切都处理得当,它应该真的是零,或者大部分是零。
我尝试在操作前后使用 JetBrains DotMemory 使用快照,例如,我发现在 2 个快照之间可能只有 4 个对象在迭代开始时不存在 - 所有四个都是未记录的实例System.Windows.Forms.Command。然而 USER 对象的数量却增加了!
这向我表明代码中的某些内容没有正确处置/释放其中一些非托管 USER 对象。问题显然不是托管对象(除了 4 个虚假的 Command 对象,我不知道它们在做什么)。
我的代码不使用任何非托管资源 - 它正在调用 Microsoft 类和 Infragistics 类。现在我知道 Infragistics 以泄漏而闻名,但通常这与静态绑定对象有关,并且根据 DotMemory 并没有在这里发生(已经注意删除这些对象的使用)。我还希望重复操作会显示线性泄漏。
所以我的问题真的是:如何找出正在使用的 USER 和 GDI 对象?内存分析器似乎没有涵盖这一点。我已经为 USER 对象尝试了 UISpy,但在这种情况下似乎几乎没用。它显示了我希望使用的所有那些,但没有显示额外的。
我更关心 USER 对象,因为它们增长得更快,并且更有可能在应用程序重新启动之间打破 10,000 个限制,但虚假的 GDI 增加当然也让我感兴趣。
我不反对这里和那里的一点点泄漏,因为它可能不会造成影响,我宁愿开发时间被高效地花费,而不是诊断可能存在于第 3 方组件中的小泄漏和很难修复。
【问题讨论】:
-
修复 c# vb.net 标签,因为我没有看到这些语言的任何代码,并运行 10000x 进行实际测试而不是 10x
-
您是否运行了 Visual Studios 静态代码分析并修复了所有“未正确处理”消息?
-
Form.Command 是一种领先者,您应该在代码中查找旧的 .NET 1.0 Menu、ContextMenu 和 MenuItem 类。他们使用 Windows 中对菜单的遗留内置支持,这将使 USER Object 计数器打勾。如果您破解了 MenuItem 以显示图标或位图,则还有 GDI 对象。这样的黑客攻击本身就是一种很好的泄密方式。否则,USER 对象泄漏是损坏的 Controls.Clear 或 Controls.Remove/At 代码的标准信号。此类代码必须处理已删除的控件,但通常不会。
-
@nvoigt - 静态代码分析在其他地方发现了一些未处理的绘图对象。但在这方面什么都没有。
-
@cladius - 对不起,我的标签不好。已更正
标签: .net memory-leaks