Posts Tagged ‘ GC ’

Finding a Memory Leak in a .Net Application

Do You Have a Leak?

What do you do when you think your application has a memory leak?

I’m sure there are many options but this posting is about my experience with Red Gates ANTS memory profiler 5.1.

About Memory Management and the GC

There have been books written on this so I’m not going to attempt to explain. However I can’t stress enough how important it is to have at least a basic understanding about how the Garbage Collector works.

To compliment their products Red Gate have created a series of easy to understand on-line video’s about .Net Memory Management nicely broken down into several 5-10 minutes segments. These video’s are FREE so watch them!

If the video’s are not in depth enough for you, any article on the subject by Jeffrey Richter should satisfy your need for detailed explanations. Start with this one.

My Leak

Every time I opened and closed one of my controls, which was getting opened in a modal window, the memory used by the application increased and never went back down again. Which is weird because doesn’t .Net handle all memory management for me?

Do it does not.

So what is going on? The control in question has a dispose method, there’s nothing really tricky going on (no database connections etc) so how do I find out exactly what is causing the leak?

Finding the Leak

Enter ANTS memory profiler. I fire up the profiler, select my .exe and click ‘Start Profiling’.

Easy.

The app starts like normal but now the profiler has it under a microscope. Expect your app to run more slowly and make sure you have plenty of RAM.

I navigate to the screen where I can ‘launch’ the control that is leaking, then click ‘Take Memory Snapshot’.

Then I open and close the modal window say six times then click ‘Take Memory Snapshot’ once more.

Now we have two memory snapshots which we can compare. Stop Profiling for now, two is enough.

Click ‘Class List’, then in the grid click on the ‘Instance Diff (+/-)’ column header to sort by instance differences.

What we can clearly see now is a list of objects that are ‘alive’ in the program. What we care about is the difference in live instances from the first snapshot to the second. The ‘Instance Diff’ column provides this info. Now if we have a leak we should see an extra 6 live instances for our leaky control. So scroll down to the group of +6 items.

There are a couple of things of interest here in the profiler. First is yes we can see an extra six instance of our leaky control. Secondly, notice that ANTS puts your controls in bold. In this case we are looking for a specific problem but if you wanted to check for general memory leaks you can easily use the app for a while then scroll down until you see which of your objects is regularly increasing its instance count.

Ok great, we know it leaks, now what?

Dig a Little Deeper

Highlight the leaky object and click Instance List.

That will then show all 6 instance, just select one then click the ‘Object Retention Graph’ button.

In my case the graph appears empty, until I uncheck the ‘Hide’ box.

Now there’s some useful info…

In fact this tells me that there are several KeyEventHandlers that are stopping the GC from collecting my control.

Cool so back to the code and I add some code to unregister the handlers in the Dispose method.

_previousButton.Click -= PreviousButtonClick;
 _familyNameText.KeyDown -= Navigate;
 _givenNamesText.KeyDown -= Navigate;
...

Rebuild the solution and re-run the profiler. Take the initial snapshot, open close the leaky form half a dozen times, take the second snapshot.

Compare.

Now there are no more live instances of the leaky control! Our memory leak has been resolved.

Very easily!

Summary

It is almost certain that somewhere in your application there is a memory leak. With the right tool finding and resolving these leaks can be really easy, it just takes a little bit of time to familiarise yourself with the way the tool works.

The tools aren’t cheap but for any commercial application they are most definately worth the money. In this posting I used ANTS profiler from Red Gate, I am sure there are other tools out there that also do a great job, I just haven’t had the opportunity to use them. ANTS though is excellent (and no I do not have any association with them…beyond having bought a licence).

Events wired up to their handlers are often the ‘hidden’ cause of leaks. But even those of us who know how to manage memory in .Net often forget to do the right thing for whatever reason…usually time pressures. So I’d recommend explicitly building in some time into your project schedule to go hunting for memory leaks, find them before they go into production and everyone will sleep easier at night 🙂

Memory Leak in My .Net Application

.Net does not make memory leaks a thing of the past….but it does very nicely take away most of the burden from developers.

Our WinForms app is due to go live very soon and we’ve noticed that we have a memory leak. These are the two errors we were receiving…

OUT OF MEMORY EXCEPTIONS

We were receiving two differnt types of exceptions:-

  1. Error Creating Window Handle.
  2. A Generic Error Occured in GDI+

The errors intermittently in random parts of the application but it did seem to occur more frequently in one ‘problem’ area.

IDENTIFYING A MEMORY LEAK

Open Task Manager, goto Views -> Select Columns and check USER Objects and GDI Objects. Why do we care about these? As it turns out, if either of these numbers hits 10000 you will get an out of memory exception. User objects produces the Handle error and GDI produces the GDI error (oddly enough).

UserGDIcolumnselect

Now run your app and watch those numbers.  Ideally focus on one specific area where you can repeat an activity such as opening and closing a modal window (the memory leaks we had were occuring around creating and disposing controls.) If the numbers go up and never come down then it’s likely you have a leak (allow some time for the Garbage Collector – GC – to run).

PLEASE DISPOSE OF YOUR OBJECTS THOUGHTFULLY

So the app had a memory leak, what then? First I checked that IDispose was correctly and that we were calling Dispose where necessary.

I’m not going to discuss how to do this in this post but here’s a couple of links to get you started…

http://msdn.microsoft.com/en-us/library/b1yfkh5e.aspx
http://www.codeproject.com/KB/cs/idispose.aspx

Once this was done the User Objects count was under control. GREAT….but the GDI count was improved but there was no doubt that it was still growing unchecked. So what then? This article led me to ANTS Profiler and few interesting discoveries that I’ll discuss in my next post…

Other Resource/Useful Links

This is a very interesting article about ‘Windows are not cheap objects’
http://blogs.msdn.com/oldnewthing/archive/2005/03/15/395866.aspx