Microsoft Developer Network > Domovská stránka fór > .NET Base Class Library > GDI+ Problem with OutOfMemoryException rasied sometime from System.Drawing.Graphics.FromHdcInternal(IntPtr hdc)
Odeslat dotazOdeslat dotaz
 

OdpovědětGDI+ Problem with OutOfMemoryException rasied sometime from System.Drawing.Graphics.FromHdcInternal(IntPtr hdc)

  • 30. srpna 2008 17:40Patrick SmacchiaMVPUživatelské medaileUživatelské medaileUživatelské medaileUživatelské medaileUživatelské medaile
     
    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

Odpovědi

  • 1. září 2008 14:09nobugzMVP, ModerátorUživatelské medaileUživatelské medaileUživatelské medaileUživatelské medaileUživatelské medaile
     Odpovědět
    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.

Všechny reakce

  • 30. srpna 2008 18:30JohnWein Uživatelské medaileUživatelské medaileUživatelské medaileUživatelské medaileUživatelské medaile
     
    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.
    • UpravenýJohnWein 30. srpna 2008 18:31added .NET
    •  
  • 1. září 2008 7:30Patrick SmacchiaMVPUživatelské medaileUživatelské medaileUživatelské medaileUživatelské medaileUživatelské medaile
     
    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
  • 1. září 2008 14:09nobugzMVP, ModerátorUživatelské medaileUživatelské medaileUživatelské medaileUživatelské medaileUživatelské medaile
     Odpovědět
    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.
  • 1. září 2008 14:15Patrick SmacchiaMVPUživatelské medaileUživatelské medaileUživatelské medaileUživatelské medaileUživatelské medaile
     
    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