MSDN >
論壇首頁
>
.NET Base Class Library
>
GDI+ Problem with OutOfMemoryException rasied sometime from System.Drawing.Graphics.FromHdcInternal(IntPtr hdc)
GDI+ Problem with OutOfMemoryException rasied sometime from System.Drawing.Graphics.FromHdcInternal(IntPtr hdc)
- Hi,
Me, and users of the .NET application I am working on, sometime get an OutOfmemoryException which callstack ends up with:
Exception.Type {System.OutOfMemoryException}
Exception.Message {Out of memory.}
Exception.StackTrace {
at System.Drawing.Graphics.FromHdcInternal(IntPtr hdc)
I personally works with Windows Vista Ultimate x64, .NET 3.5 SP1, but it doesn't seems to comes from a particular version of the OS and of .NET since this problem sometime appears on x32 machines with .NET 2.0.
Example of call stacks are:
at System.Drawing.Graphics.FromHdcInternal(IntPtr hdc)
at System.Drawing.Font.GetHeight()
at System.Drawing.Font.get_Height()
or
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.SplitContainer.WndProc(Message& msg)
at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
or
at System.Drawing.Graphics.FromHdcInternal(IntPtr hdc)
at System.Drawing.Font.ToLogFont(Object logFont)
at System.Windows.Forms.RichTextBox.FontToLogFont(Font value, LOGFONT logfont)
at System.Windows.Forms.RichTextBox.SetCharFormatFont(Boolean selectionOnly, Font value)
at System.Windows.Forms.RichTextBox.set_SelectionFont(Font value)
Reflector tells me that it is the win32 methods GdipCreateFromHDC() from gdiplus.dll that returns a status equals to 3.
The problem happens rarely, but often enough to bothers some our users.
Could it be a lack of Dispose() on some handles on GDI+ objects?
Any help would be highly appreciated.
Thanks,
Patrick Smacchia
MVP Visual C#
Lead Developer of NDepend http://www.NDepend.com
Author of: Practical .NET2 and C#2 http://www.practicaldot.net
Patrick (at) Smacchia (dot) com
解答
- GDI+ generates pretty lousy exceptions, you can get OOM in error conditions that have nothing whatsoever to do with running out of memory. With this call stack, I'd say you are probably running out of GDI handles. There's a limit of 10,000 handles for a process. Not calling Dispose() on graphics objects is indeed a good way to trip the problem. You would have to get into a condition where you do lots of painting but not allocate sufficient managed objects to trip a garbage collection. That's very hard to do. Perhaps the real leak is elsewhere, CopyFromScreen() in .NET 2.0 SP1 had a handle leak for example.
Hans Passant.- 已標示為解答Zhi-Xin YeMSFT, 版主Friday, 5 September, 2008 7:09
所有回覆
- I don't think .NET GDI+ is quite ready for prime time. If you're doing something other than normal control painting, consider calling the GDI API methods directly.
- 已編輯JohnWein Saturday, 30 August, 2008 18:31added .NET
- John, so far our application is massively using GDI+ with just one case where this OutOfMemoryException was raised. It seems that only recently the number of occurences of the problem increase.
Patrick (at) Smacchia (dot) com - GDI+ generates pretty lousy exceptions, you can get OOM in error conditions that have nothing whatsoever to do with running out of memory. With this call stack, I'd say you are probably running out of GDI handles. There's a limit of 10,000 handles for a process. Not calling Dispose() on graphics objects is indeed a good way to trip the problem. You would have to get into a condition where you do lots of painting but not allocate sufficient managed objects to trip a garbage collection. That's very hard to do. Perhaps the real leak is elsewhere, CopyFromScreen() in .NET 2.0 SP1 had a handle leak for example.
Hans Passant.- 已標示為解答Zhi-Xin YeMSFT, 版主Friday, 5 September, 2008 7:09
- Hans, I think you are right, my process is certainly running out of GDI handles. Meantime, I found this following thread where several programmers have the same problem and an MSFT ends up to the conclusion that some GDI object are not properly disposed before they are collected.
http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=161567&SiteID=1
Patrick (at) Smacchia (dot) com

