Memory layout problem solving for C Struct

  • 2020-05-24 06:01:43
  • OfStack

Question: please state the instance size and memory layout of struct below


struct Struct1
{
    public byte a;
    public short b;
    public string c;
    public int d;
}
struct Struct2
{
    public byte a;
    public long b;
    public byte c;
    public string d;
}
struct Struct3
{
    byte a;
    byte b;
    long c;
}
struct Struct4
{
    byte a;
    long b;
    byte c;
}

1 will look at the answers again to see if they differ significantly from your understanding. In fact, the memory layout of struct and class is determined by StructLayoutAttribute's construction parameters: LayoutKind enumeration, struct by the compiler to add LayoutKind.Sequential, class by the compiler to add LayoutKind.Auto. The experimental data of Sequential can be summarized as follows:

1. For struct without reference type: in the order defined, the memory layout is the same as c, c++. Such as:

Byte a;

Byte b;

Long c;

Size is a, b fills 4 bytes, c fills 8 bytes

Byte a

Long c

Byte b

The size of a is filled with 8 bytes, c with 8 bytes, b with 8 bytes

2. For fields with reference type struct: greater than 4 bytes - > Reference field - > Fields less than 4 bytes

For fields less than 4 bytes in size, memory layout is the same as rule 1 if the size is the same in defined order. One thing to note is that if the field is of type struct, it will always be last.

So the answer above is:

Struct1: c (4) > d(4) - > b(2) - > a(2)

Struct2: b (8) > d(4) - > a(1)c(1) fills in 2 bytes

Struct3: a(1)b(1) fills 2 bytes - > c(8)

Struct4: a(1) fills 7 bytes - > b(8)- > c(1) fills in 7 bytes

If you want to experiment 1 with your own hands, you'll need to use SOS.dll for debugging (there are many articles and blogs on SOS configuration and usage introduction). Take struct1 as an example:

Struct1s1 = new Struct1();

s1.a = 1;

s1.b = 15;

s1.c = "c";

s1.d = 32;

.load sos

C:\WINDOWS\ Microsoft.NET \Framework\ v2.0.50727 \ sos.dll

!clrstack -a

PDB symbol for mscorwks.dll not loaded

OS Thread Id: 0x15fc (5628)

ESP EIP

0041ee3c 03ba01aa Test_Console.Class12.Main()

LOCALS:

0x0041ee84 = 0x01b02b0c

0x0041ee74 = 0x00000020

0x0041ee68 = 0x00000000

0x0041ee50 = 0x00000000

0041f104 6ebd1b4c [GCFrame: 0041f104]

.load sos

C:\WINDOWS\ Microsoft.NET \Framework\ v2.0.50727 \ sos.dll

! name2ee *! Test_Console.Struct1 // get the method table address for Struct1

PDB symbol for mscorwks.dll not loaded

Module: 6d5d1000 (mscorlib.dll)

--------------------------------------

Module: 00192c5c (Test_Console.exe)

Token: 0x02000012

MethodTable: 00193828

EEClass: 007a45b4

Name: Test_Console.Struct1

! clrstack-a // gets the address on the stack of the struct1 instance

OS Thread Id: 0x1438 (5176)

ESP EIP

003eef0c 008f00c9 Test_Console.Class12.Main()

LOCALS:

0x003eef1c = 0x01c12b0c

003ef17c 6ebd1b4c [GCFrame: 003ef17c]

! dumpvc 00193828 0 x003eef1c / / view layout value types

Name: Test_Console.Struct1

MethodTable 00193828

EEClass: 007a45b4

Size: 20(0x14) bytes

Fields:

MT Field Offset Type VT Attr Value Name

6d84340c 400001c a System.Byte 1 instance 1 a

6d83e910 400001d 8 System.Int16 1 instance 15 b

6d8408ec 400001e 0 System.String 0 instance 01c12b0c c

6d842b38 400001f 4 System.Int32 1 instance 32 d

In the memory window, you can see that the memory layout is:

0x003EEF1C 01c12b0c 00000020 0001000f

Here I'm going to show you that using dumpvc gives you an size, which is 20 bytes, which is 8 bytes more than we calculated, and I understand that because the reference type has an additional 8 bytes (syncblkindex + methodtableaddress) so size plus 8.


Related articles: