2

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.

frankie
  • 728
  • 1
  • 10
  • 28
  • You can look at metadata for object size. Here you can find the code. https://github.com/mumusan/dotnetex – Dmitrii Dovgopolyi Jun 22 '14 at 11:24
  • @Dmitry Dovgopoly: I am not looking for XStruct size. I am interested in why it is not displayed as stack object. – frankie Jun 22 '14 at 11:26
  • It didn't print out your double variables either. Apparently, value type locals are not printed. http://msdn.microsoft.com/en-us/library/bb190764(v=vs.110).aspx – usr Jun 22 '14 at 11:53
  • @usr are there any ways to print value type locals? Any parameter for !dso or something else? – frankie Jun 22 '14 at 12:59

1 Answers1

3

!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.

Community
  • 1
  • 1
Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
  • Any reason in particular not just to use `sizeof(XStruct)`? – jakobbotsch Jun 22 '14 at 13:50
  • Sure, it is not usable for any struct types that have fields of a reference type. – Hans Passant Jun 22 '14 at 14:04
  • Neither is yours as you cannot declare pointers to non-unmanaged types. – jakobbotsch Jun 22 '14 at 14:05
  • No problem. Interestingly, if the struct contains another value type, you can declare pointers to those and check the spacing between those pointers, even if the struct also contains reference types. – jakobbotsch Jun 22 '14 at 14:09
  • @Hans Passant: I have even more elegant way to get structure size is to declare structure as a field of reference type and than use !dumpvc over it to get it size and other info. My real point of interest is how to obtain info about Stack states just like with !dso for reference type. Is there any way to get it worked? – frankie Jun 22 '14 at 19:46