DCSIMG
What Every .NET Developer Should Know To Do With Sos.dll - Doron's .NET Space

What Every .NET Developer Should Know To Do With Sos.dll

This week had been a debugging week. Up until now my only debugging tool had been Visual Studio, but in some cases it just isn't enough. For instance, suppose you've noticed that your web application in production or in development  is currently utilizing a suspicious amount of memory. You want to know exactly what's taking up all this memory. Visual Studio does not normally allow you to find out, and so comes in sos.dll, which is a debugging extension for managed code.

You can use sos.dll with windbg or from within Visual Studio. If this is production code we're talking about, you'll probably use windbg, But learning yet another tool might be discouraging for some developers, so I believe that it's better at first to learn it via Visual Studio, and then move to windbg and find out that it's pretty much the same, just more powerful and comfortable.

So, the basic scenario we're talking about is find out which type of objects are in our memory. First we need to attach the debugger to our application process (while making sure we enable managed & native debugging, otherwise sos.dll won't work), and set a breakpoint in a certain place. Once the breakpoint is hit, we can start the action.

immediate1

As you can see in the picture, the first command we ran was !dumpheap -stat this gives you a summary of all the types that are currently in the managed heap, and their memory consumption. If we go all the way down, we will see the most "problematic" types, that is, that consume the most memory.

The next step is to pick one of these types and investigate why are they there. For the sake of the example, let's pick System.CodeDom.Compiler.CodeDomConfigurationHandler that you can see in the image. Its memory consumption is insignificant, but it may seem suspicious to us, as our application doesn't use CodeDom at all. So let's find out the address of this object (we can see in the count parameter that there is only one of those).

immediate2

Our second command was !dumpheap -type System.CodeDom.Compiler.CodeDomConfigurationHandler. This will give us all the locations in the memory of a certain type (well, every type that contains the specified string). So we can see that our object resides in Heap 0 at the address 015b0f08. Now, let's find out the reason for it's existence, or in other words - who points to this object?

immediate3

We ran the command !gcroot [address]. This tells us the exact route that leads to our object. In other words, the reason this instance of CodeDomConfigurationHandler isn't garbage collected is because it is referenced by RuntimeConfigurationFactory which is referenced all the way up to System.Web.HttpContext. Ah. So that is where our object belongs, it is required by one of the of the members of HttpContext. Nothing wrong with that, then.

Of course this was a bit of a contrived example, but this process in general is useful and not that difficult. Remember the steps:

  1. Attach to the process (allow native mode) and hit a breakpoint.
  2. Bring up the immediate window and hit .load sos.dll.
  3. !dumpheap -stat and look for something suspicious, usually memory consumption that seems too high.
  4. !dumpheap -type [suspicious type name] -> get addresses.
  5. !gcroot [suspicious type address].

There is a lot more you can do with sos.dll and windbg, and I would like to recommend Tess' great blog on the subject. That girl is quite the hacker and a real debugging detective, I tell you (a genuine Gashash Balash as we would call her in Israel). Her blog contains tons of walkthroughs for many different scenarios.

Happy Passover folks!

Published Sunday, April 20, 2008 1:31 PM by dorony
תגים:

Comments

No Comments

Leave a Comment

(required) 
(required) 
(optional)
(required) 

Enter the numbers above: