Reliable approach to discovering and fixing .NET memory leaks

Tracking down memory leaks can be very time consuming and inexact but WinDbg helps. A lot. WinDbg is a free, very low level debugger you can download from Microsoft. If you’ve only done debugging through an IDE, such as Visual Studio, it may be a little intimidating at first but you really only need to know a couple of commands. You can even do this analysis on production systems by creating a quick memory dump on the server, copying the dump over to a development workstation, and then opening the dump file in WinDbg.

The basic strategy to follow is:

  1. Use the application
  2. Force Garbage Collection
  3. Using WinDbg inspect the application’s memory, looking for objects of a certain type should have been collected
  4. If objects are found, determine what references to them is preventing collection.
  5. Fix the problem
  6. Repeat as needed

Without WinDbg, or a similar tool, there would be much guesswork or application instrumentation to locate leaked objects.

Here are the detailed instructions:

  1. Restart the application
  2. Exercise the functionality to test for memory leaks. Be sure to repeat actions several times to magnify the results.
  3. Force the garbage collector to run (GC.Collect() and GC.Collect(gen, GCCollectionMode.Forced)). The GC is non-deterministic so you should do this a few times until you notice memory for the process is no longer changing in Task Manager.
  4. Attach to the application process in WinDbg. If you’re debugging an ASP.Net web application attach to w3wp.exe.

  5. Next, load the .Net debugging extensions by entering the following command (the command entry is at the very bottom of the screen)

     

    .loadby sos clr
    
  6. Get a list of uncollected objects. Replace <TypeName> with the name of a class that you would expect to not be loaded in memory. In the example below: VC3.TestView.Business.Student.

     

    !dumpheap -type <TypeName>
    

    The command will list the memory address objects of that type that have not yet been garbage collected, followed by some statistics on the objects. You’ll need to cross reference the type name (MT) in the Statistics section with objects in the heap to locate the address of a single object.

     

     

  7. Now, use WinDbg which will tell you what GC rooted reference is keeping the object alive

     

    !gcroot -nostacks <ObjectAddress>
    

 


About this entry