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)

  • 2008年8月30日 17:40Patrick SmacchiaMVPユーザーのメダルユーザーのメダルユーザーのメダルユーザーのメダルユーザーのメダル
     
    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

回答

  • 2008年9月1日 14:09nobugzMVP, モデレータユーザーのメダルユーザーのメダルユーザーのメダルユーザーのメダルユーザーのメダル
     回答済み
    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.

すべての返信

  • 2008年8月30日 18:30JohnWein ユーザーのメダルユーザーのメダルユーザーのメダルユーザーのメダルユーザーのメダル
     
    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 2008年8月30日 18:31added .NET
    •  
  • 2008年9月1日 7:30Patrick SmacchiaMVPユーザーのメダルユーザーのメダルユーザーのメダルユーザーのメダルユーザーのメダル
     
    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
  • 2008年9月1日 14:09nobugzMVP, モデレータユーザーのメダルユーザーのメダルユーザーのメダルユーザーのメダルユーザーのメダル
     回答済み
    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.
  • 2008年9月1日 14:15Patrick SmacchiaMVPユーザーのメダルユーザーのメダルユーザーのメダルユーザーのメダルユーザーのメダル
     
    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