Tech talk: CLR Memory Diagnostics

Today’s tech talk we discussed the recent release from Microsoft of ClrMD that lets you attach and debug processes using an exposed API. You used to be able to do this in WinDbg using the SOS plugin, but now they’ve wrapped SOS in a managed dll that you can use to inspect CLR process information. The nice thing about this is you can now automate debugging inspections. It’s now as easy as

int pid = Process.GetProcessesByName("TestApplication")[0].Id;

using (DataTarget dataTarget = DataTarget.AttachToProcess(pid, 5000))
    string dacLocation = dataTarget.ClrVersions[0].TryGetDacLocation();
    ClrRuntime runtime = dataTarget.CreateRuntime(dacLocation);

    ClrHeap heap = runtime.GetHeap();

    foreach (ulong obj in heap.EnumerateObjects())
         ClrType type = heap.GetObjectType(obj);
         ulong size = type.GetSize(obj);
         Console.WriteLine("{0,12:X} {1,8:n0} {2}", obj, size, type.Name);

ClrMD lets you take stack snapshots of running threads, iterate through all objects in the heap and get their values out, show all loaded modules and more. If you combine it with ScriptCS you’ve got a really powerful debugging tool. What I liked about ClrMD is that you can use the same API to attach to running processes (in modes where you can pause the app while running, or run without pausing the attached app) as you can with process dumps.

While it is nice to be able to inspect the heap and stacks, I found that it’s not totally trivial to get object information. Since all your queries return pointers to values on the heap (unless its a primitive object), you need to recursively go through the entire object reference to find all the details. If you have the source, symbols, and a crash dump I think it’s easier to just toss it into visual studio to get this information. Still, if you don’t have access to this and need to investigate or automate error detection in a low level fashion, then this is an amazing tool.

For more reading check out

Leave a Reply

Your email address will not be published. Required fields are marked *