Investigation of CLR via SOS

2019-02-19 10:02发布

问题:

Currently I am digging deeper into CLR and try to find proper size of my managed objects.

I have two simple types:

XClass

    class XClass
{
    public XStruct StructField = new XStruct();
    public int IntField;
    public double DoubleField;
}

and XStruct

struct XStruct
{
    public short ShortField;
    public long LongField;
}

Also cosider code snippet where this objects are involved:

static unsafe void Main(string[] args)
{
    double angle = 0.34;

    {
        double anotherDouble = 1.49;

        XStruct xStruct = new XStruct();
        xStruct.ShortField = 12;
        xStruct.LongField = 1234567890;

        XClass classObject = new XClass();
        classObject.DoubleField = angle + anotherDouble;
        classObject.IntField = 123;
        classObject.StructField = xStruct;

        <<<<<<<<BREAKPOINT>>>>>>>

        xStruct.ShortField = 3;
    }

    double* ptr = &angle;

    Console.WriteLine(*(ptr - 1));
    Console.ReadKey();
}

So, I try to get some info about XStruct placed in stack, but I cannot find it there.

!dso
PDB symbol for clr.dll not loaded
OS Thread Id: 0x1f94 (8084)
ESP/REG  Object   Name
0018EF1C 0260252c ConsoleApplication2.XClass
0018EF20 0260252c ConsoleApplication2.XClass
0018F290 0260252c ConsoleApplication2.XClass
0018F2C4 0260251c System.Object[]    (System.String[])
0018F2E0 0260252c ConsoleApplication2.XClass
0018F2E8 0260252c ConsoleApplication2.XClass
0018F30C 0260251c System.Object[]    (System.String[])
0018F3C0 0260251c System.Object[]    (System.String[])
0018F51C 0260251c System.Object[]    (System.String[])
0018F554 0260251c System.Object[]    (System.String[])
0018FA90 02601238 System.SharedStatics

Please, explain why ConsoleApplication2.XStruct is not displayed and why ConsoleApplication2.XClass is displayed as object in stack. I thought that XClass (as normal reference type) should be placed in heap. Or may be my understanding of !dso is incorrect.

Thanks.

回答1:

!dso == Dump Stack Objects. Focus on "Objects", a struct is not an object.

The only reason that SOS is capable of finding objects references at all is because it can use the metadata that the jitter generates when it compiles a method. This data is used by the garbage collector when it performs stack walks to find object references back. You can read more about it in this answer. Value type values are missing from this metadata, the GC doesn't care about them.

You can infer the size of a struct by creating an array of them, giving the first field of the struct a distinctive value. Look at the array with the VS debugger, Debug + Windows + Memory + Memory1, put the variable name in the Address field. You'll the struct values back in the hex dump, after the array header. Do beware that structure sizes depend on the CLR version and the bitness of the process so only ever use this info as a hint.



标签: c# .net clr