【问题标题】:.NET Can't diagnose USER object leak.NET 无法诊断 USER 对象泄漏
【发布时间】: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


【解决方案1】:

识别需要一段时间,但经过大量调试和注释代码后,我将其范围缩小到 Infragistics UltraTextEditor。如果我设置 AlwaysInEditMode=True 那么我得到这个泄漏。如果我将其设置为 False,那么我不会。同样,如果我将另一个 UltraTextEditor 添加到用户控件(并且不对其执行任何操作)并设置 AlwaysInEditMode=True ,那么我也会得到泄漏。

我厌倦了在一个小型测试项目中重现这一点,但无法继续调查。

我最终发现了一个面板,该面板在用户控件深处被移除(当显示部分被有效折叠时),其中包含 Infragistics UltraTextEditor 的三个实例以及一些其他 Windows 控件。现在似乎面板和控件正在被垃圾收集(没有引用),但它们没有被处置。这对于非 Infragistics 控件似乎无关紧要(我猜它们不使用非托管资源?)但是 Infragistics 控件有一个未清理的 USER 对象。 Infragistics UltraTextEditor 的工作方式有点奇怪。它由两个文本框组成,一个我认为是标准的 MS 文本框,另一个是 Infragistics 开发的文本框。在正常操作中,当控件具有焦点时显示一个,而在失去焦点时显示另一个。通过设置 AlwaysInEditMode=True 我认为它必须在那时处理其中一个(具有非托管资源的那个)。因此,如果没有设置这个,当控件最终被垃圾回收而没有被释放时,它一定会留下未释放的非托管资源。

所以,开发人员错误。但这是一个真正的艰难。内存分析没有显示问题。并且没有任何东西可以让您追踪野蛮的 USER 对象。如果我能够看到它们所代表的内容,那么识别模式和整个问题会容易得多。再加上使用 Infragistics 有点模糊,因为作为一个黑匣子,你并不真正知道或不需要知道幕后发生的事情。直到它不起作用为止都很好!

对于非线性特性,我仍然没有答案,但该框架当然会在后台执行各种操作,响应鼠标移动和进入/离开事件。需要一个像样的 USER 对象分析器!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-24
    • 2018-10-24
    • 2012-10-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多