【发布时间】:2011-03-02 10:30:01
【问题描述】:
我偶尔会遇到以下跟踪崩溃:
System.OutOfMemoryException: Out of memory.
at System.Drawing.Graphics.FromHdcInternal(IntPtr hdc)
at System.Windows.Forms.PaintEventArgs.get_Graphics()
at System.Windows.Forms.Control.PaintBackColor(PaintEventArgs e, Rectangle rectangle, Color backColor)
at System.Windows.Forms.Control.PaintBackground(PaintEventArgs e, Rectangle rectangle, Color backColor, Point scrollOffset)
at System.Windows.Forms.Control.PaintBackground(PaintEventArgs e, Rectangle rectangle)
at System.Windows.Forms.Control.OnPaintBackground(PaintEventArgs pevent)
at System.Windows.Forms.ScrollableControl.OnPaintBackground(PaintEventArgs e)
at System.Windows.Forms.Control.PaintWithErrorHandling(PaintEventArgs e, Int16 layer, Boolean disposeEventArgs)
at System.Windows.Forms.Control.WmEraseBkgnd(Message& m)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.ScrollableControl.WndProc(Message& m)
at System.Windows.Forms.ContainerControl.WndProc(Message& m)
at System.Windows.Forms.UserControl.WndProc(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
正如您所见,跟踪中没有我的代码,所以我很难找到原因。谷歌搜索似乎没有定论,但通常指向某处的 GC 句柄泄漏,但在最近的崩溃之后,我的内存使用情况是:
Handle count:16,283,
Private Bytes:995,440K,
Virtual Bytes:1,628,208K,
Working Set:866,892K,
GC Heap Size:158,841K,
GDI Objects:402,
User Objects:1,607
这似乎并没有什么特别之处。另外,我经常使用 .net 内存分析器来管理泄漏。
不幸的是,我的应用程序很大,有很多窗口,所以我的第一个问题是:如何确定是哪个窗口导致了所有问题?
当然我的第二个问题是:如果没有句柄泄漏,是什么导致了异常!?
编辑:
抱歉,我无法发布任何代码:它是一个庞大的代码库,并且异常并不能准确地给我任何线索,说明哪一部分可能是问题所在。
我听说有 10,000 个句柄的限制,但这个应用程序在历史上一直运行良好,只有 15,000 个,所以我认为限制是在其他方面:GDI 句柄或用户对象可能是?
只是为了确保,我检查了句柄并没有泄漏,因为它们都是在启动时分配的,并且不会随着使用而增加。
让我修改一下我的问题:鉴于这些信息,下一步应该采取什么行动?我已经安装了进程资源管理器,并成功地从其中一次崩溃中获得了完整的内存转储,但真的没有使用任何一种方法来诊断此类问题的经验(直到现在 .net 内存分析器已经足够了)
【问题讨论】:
-
您希望我们猜测您的代码做错了什么?这比你只发布要困难得多。
-
Mark Russinovich:“[a]任何在任何给定时间点打开超过一万个句柄的进程都可能设计不良或存在句柄泄漏”。请注意,“内存不足”异常并不一定意味着您的 内存 不足;此错误代码在 Win32 API 中多次使用,表示您已用完 资源。您可以使用Process Explorer 快速检查重复项。
-
句柄计数方式太高。不知道你是如何设法让它超过 10,000 的,这是进程 afaik 的正常配额。不过有些东西泄漏得很厉害。
-
欢迎来到 Stack Overflow :) 请编辑您的问题以提供更多信息或说明。此外,您可以将 cmets 留在个别答案下(使用“添加评论”链接)。答案仅用于此目的,答案 - 不是对他人的回复。
-
下一步是减少您打开的句柄的数量。无论 Windows 施加什么硬限制,对于普通应用程序而言,您有太多的方式。因此,您会遇到异常并不出人意料。正如 Femaref 建议的那样,寻找您正在创建 GDI+ 对象(例如画笔、钢笔等)但不处置它们的地方。最佳实践是将创建和使用包装在
using语句中,该语句将在您使用完对象后自动处理对象的处置。检查您的Paint事件处理程序;这是最有可能发生泄漏的地方。
标签: .net out-of-memory