CodeBetter.Com
CodeBetter.Com
RSS 2.0 via Feedburner
           Do you Twitter? Follow us @CodeBetter

Patrick Smacchia [MVP C#]


A frustrating GDI bug

In the history of bugs feedback from users of NDepend, there are 4 unresolved OutOfMemoryException unhandled. They all have been reported by different users, on different version of the product and the call stack is different for all of them. The only common point is that their call stack all begins with: System.Drawing.Graphics.FromHdcInternal(IntPtr hdc). These bugs have been classified as unreproductible bug so far since we cannot reproduce it on our machines despite all our efforts and the users can’t reproduce it neither.

For the next version of NDepend, we are using a new library and suddenly we got once or twice a day such OutOfMemoryException popping from FromHdcInternal(…).  After crawling the web I found this thread where several programmers complain for the same problem and after a lot of ramblings an MSFT conclude by: Bottom line: make sure you explicitly dispose *all* your Graphics objects.

The problem is then if you don’t dispose many GDI object (Font, Brush…) you might get such OutOfMemoryException. I also opened my own thread on this, and Hans Passant explains that it is likely that the process is running out of GDI handles.

After reverse engineered the library the next version of NDepend will rely on, I found indeed many undisposed GDI objects. We are then in the process of tracking unreleased GDI objects in our code and you know what, it reminds me the (not good) old days when I was programming with C++. Hopefully, I found the tool .NET Memory Profiler convenient to track undisposed objects.

Despite our efforts, we know we won’t get all GDI objects disposed, just because some libraries we are relying on are and will still leak. To avoid users a bad experience, we will then add a global catch of all OutOfMemoryException where the call stack begins with FromHdcInternal. From a user experience perspective, very rarely some GDI drawing will miss a detail, not clean but still acceptable. From a programmer perspective such a global catch makes me sick but do we have the choice?

I notice that OutOfMemoryException seems to be the common GDI exception for many problems. When you are tracing a small GDI object, you can get such exception as explained here. I also reported a similar exception to MS (see here) when creating a LinearGradientBrush with the 2 same points. The answer is that because of backward compatibility this can’t be changed. 



Comments

Peter Ritchie said:

It's amazing how prevalent problems with two-dimensional shapes with identical top-left and bottom-right coordinates are.  Although you don't get an exception, drawing a line with a top-left coordinate the same as the bottom-right does nothing: connect.microsoft.com/.../ViewFeedback.aspx

# September 3, 2008 10:17 AM

Art Scott said:

" ... The answer is that because of backward compatibility this can’t be changed.  ..."

Of course that is not an answer, its an excuse.

The good news is that there is competition, which tends towards real answers and less excuses.

Bad news, it will take time, and someone (hello) deciding to assign the resources to it.

# September 4, 2008 2:04 PM

Leave a Comment

(required)  
(optional)
(required)  

Enter the numbers above:
Add

About Patrick Smacchia

Patrick Smacchia is a Visual C# MVP involved in software development for over 15 years. After graduating in mathematics and computer science, he has worked on software in a variety of fields including stock exchange, airline ticket reservation system as well as a satellite base station at Alcatel. He's currently a software consultant and trainer on .NET technologies as well as the lead developer of the tool NDepend which provides numerous metrics and caveats on any compiled .NET application. He is the author of Practical .NET2 and C#2, a .NET book conceived from real world experience with 647 compilable code listings. Check out Devlicio.us!

Our Sponsors