Debugging Managed Memory, Handle, GCHandle Leaks, Exceptions and Fragmentation with WinDbg

Assuming you already have WinDbg installed (X86 bit for your 32 bit applications, and the appropriate 64 edition for your 64 bit applications) , after startup in administration mode, you’ll want to:

1) Attach to your application process or run directly from WinDbg

2) For .Net 4.0 and above run .loadby sos clr or .loadby sos mscorwks for .Net 2.0

3) Update your symbol path so you have all the debug information that you’ll need e.g. ” *srv*c:\symbols*http://msdl.microsoft.com/downloads/symbols* “. You’ll also want to browse and add the location of the pdb files for you application.

4) Just like the VS debugger, press F5 to resume execution and CTRL+BREAK to break at any time.

5) In WinDbg, run !analyze -v (to force a load of the symbols – you’ll only need to do this the first time)

6) At any point in time when you’re at a break point you can

  •  View the CLR stack with !CLRstack
  •  View the managed threads with !Threads
  •  View combined managed and unmanaged call stack with !dumpstack
  •  View unmanaged code stack kL

Fore more useful commands check David Douglass’s SOS Cheat Sheet or Alejandro Campos Magencio SOS Cheat Sheet

Managed memory leak

Exceptions

  • For heap information on a particular type of Exception run !DumpHeap -type Exception
  • To break on all CLR exceptions run sxe clr
  • To view the last thrown exception run !pe

For further details check Alejandro Campos Magencio’s Managed Debugging with WinDbg article

Handle leaks

  • Turn on handle tracing with !htrace -enable
  • Check handles with !handles
  • Check specific handle stats with !handles <address>

For further details check Toby Opferman’s Handle leaks article

GChandle leaks

  • For stats on GCHandles run !GCHandles
  • For stats on what could potentially be a GCHandle leak, run !GCHandleLeaks

For further details check Alejandro Campos Magencio’s Managed Debugging with WinDbg article

Memory Fragmentation
Out of memory exceptions might also indicate memory fragmentation.

  • !finalizequeue – to get details on the finalization queue and compare two results to see if there are any glaring increases in the objects. For example a huge jump in generation 2 objects but 0 objects ready to be finalized.
  • After that you’ll want to look into the object that’s in the finalization queue using !do <address>. You can obtain the object addresses by listing out the dwords (using dd <starting address> <ending address>). For example, using the ending address of the 2nd generation minus the size of the object in question as the starting address, and the end of the 2nd generation as the ending address). For more details on this visit Shreous
  • !gcroot -nostacks <object memory address> – To see the references for the object in question

Finally for a list of the extension commands: SOS Debugging Extensions.

Advertisements

2 comments

  1. Bret

    Very helpful post, i used most of the functions in looking at my dump file. Is there a recommended number of large items and the size of them that can remain fragmented on the heap? Having trouble tracking down a memory leak in our application

    • jkhk

      I’m not aware of any. When you say you’re looking at your dump file, are you actually looking at multiple dump files for comparison to see where the memory is growing (it’ll be easier if you can hook into the running process). It might be worth looking into UMDH or AQTime if you haven’t already.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s