Search code examples
c#.netwindbgsosclrmd

Trying to find object roots using CLR MD


Here is my class

namespace MyNamespace
{
    public class MyClass
    {
        private byte[] imageBytes = null;

        public MyClass() { }

        public void LoadImage(string filePath)
        {
            Image img = Image.FromFile(filePath);
            using (MemoryStream mStream = new MemoryStream())
            {
                img.Save(mStream, img.RawFormat);
                imageBytes  = mStream.ToArray();
            }
        }

        public void RemoveImage()
        {
            imageBytes = null;
        }
    }
}

And this is how its used

static void Main(string[] args)
    {
        MyClass mc = new MyClass();

        mc.LoadImage(@"C:\Images\myImage.jpg");

        Console.WriteLine("take process dump now...");
        Console.Read();
        mc.RemoveImage();
    }

I run the program and take a process snapshot. No surprise, here is what I found about the references of MyClass.

0:000> !DumpHeap -type MyClass
         Address               MT     Size
0000000002b92e08 000007fe73423a20       24     

Statistics:
              MT    Count    TotalSize Class Name
000007fe73423a20        1           24 MyNamespace.MyClass
Total 1 objects
0:000> !GCRoot 0000000002b92e08 
Thread 3b3c:
    00000000004eef90 000007fe7354011f MyTestApp.Program.Main(System.String[]) [c:\Projects\MyTestApp\Program.cs @ 17]
        caller.rsp-30: 00000000004eefb0
            ->  0000000002b92e08 MyNamespace.MyClass

Found 1 unique roots (run '!GCRoot -all' to see all roots).

Now I would like to see if I can get same roots for MyClass instance present in same dump file using CLR MD . For that, I am using GCRoot sample. One of inputs to this application is ulong obj. I am not really sure how to get this for MyClass instance so what I have done is that within Main method of GCRoot sample, I added followinng code.

foreach (ulong obj2 in heap.EnumerateObjects())
{
   ClrType type2 = heap.GetObjectType(obj2);
   if (type2.Name.StartsWith("MyNamespace.MyClass") )
       obj = obj2;
}

This way I see that obj is getting a valid value but the problem is that following line of code doesn't find any node as always returns a NULL.

Node path = FindPathToTarget(heap, root);

As a result, I am not sure how can I get roots to MyClass instance from this dump file. Any suggestions will be highly appreciated.


Solution

  • ClrMD could definitely be used to create the same output as !GCRoot, the GCRoot sample is just not as elaborated as the windbg !GCRoot command.

    In your case, the object "MyClass" is a root (local var from main thread) and the sample returns nothing.

    You can check the ClrRoot returned by Heap.EnumerateRoots() and you will find your object of type "MyClass".