如何调试GDI对象泄漏?

Xen*_*tSs 5 .net gdi winforms

我不太清楚如何去做这件事.它是一个大型应用程序,我们在大多数表单上都有GDI对象"泄漏".

有帮助的工具吗?有关于如何使用这种工具的教程吗?

我应该开始从我们的表单中删除代码,直到我缩小罪犯的范围?(有很多代码).

Han*_*ant 17

很少超过GDI对象的10,000个对象限制,当你不自己调用他们的Dispose()方法时,垃圾收集器会处理它们.更可能的故障模式超出了Windows的对象限制.在Winforms中很容易做到,Controls.Clear()或Controls.Remove()会在你没有明确处理删除的控件时匆忙到达那里.垃圾收集器无法清理它们.

您可以从Taskmgr.exe,Processes选项卡中获得良好的诊断.查看+选择列并勾选句柄,用户对象和GDI对象.使用它时,请注意这些数字.其中一个稳定攀升的数字是一个明确的迹象,当它拒绝再给你时,你会让Windows轰炸你的程序.每个默认配额为10000.USER对象表示您对Controls.Clear/Remove有问题,GDI对象是指示您正在泄漏System.Drawing对象的对象.Perfmon.exe是一个很好的工具,可以查看垃圾收集器是否经常运行以释放未处置的System.Drawing对象.

有了共同的智慧,在必要时明确地调用Dispose()是一种很好的做法.特别是对于Image和Bitmap对象,它们只占用很少的GC内存,但是很多非托管内存,当你不处理它们时很容易用OOM轰炸一个程序.注意Properties.Resources中令人讨厌的陷阱,每次使用它时都会获得一个新对象,并且需要处理它.始终using在绘画代码中使用该语句.

  • 被移除的控件通过将它们置于一个称为“停放窗口”的隐藏窗口中来保持活动状态。准备好重新设置为另一个窗口的父级。非常好的功能,因为它保持本机窗口完好无损。但是,如果没有发生移动,或者它们没有被处理,它们将永远泄漏。 (2认同)
  • >> 非常好的功能,因为它使本机窗口保持完整。<< 我不明白为什么我不能保留对稍后要重新设置父级的控件的引用。在您可以轻松地自己保留参考的情况下,停车窗不是一种“有用”的以防万一的机制吗?有记录吗? (2认同)

Xen*_*tSs 1

原来我只是使用任务管理器并尝试重现该问题。我们的应用程序(以及 GDI 对象泄漏)的问题是我们使用静态对象并绑定到它。.net 3.5(至少)存在一个错误,关闭时表单不知道如何正确处理所有内容,并且某些图形对象将保留在内存中。