An object’s CLR internal structure is:
[DWORD: SyncBlock][DWORD: MethodTable Pointer][DWORD: Reference type pointer]…[Value of Value Type field]…
Object Header: [DWORD: SyncBlock]
Object Pointer: [DWORD: MethodTable Pointer][DWORD: Reference type pointer]…[Value of Value Type field]…
Every Object is preceded by an ObjHeader (at a negative offset). The ObjHeader has an index to a SyncBlock.
Sample C# code for exploring CLR object’s internal structure
namespace ObjectInternal
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
class Program
{
static void Main(string[] args)
{
Product p = new Product();
p.Price = 99;
p.Index = 25;
p.Name = "Super Product";
p.Cat = new Cateogry();
}
}
class Product
{
public int Price { get; set; }
public byte Index { get; set; }
public string Name { get; set; }
public Cateogry Cat { get; set; }
}
public class Cateogry
{
public string Name;
}
}
Sample output from SOS.dll debugger extension:
.load sos
extension C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\sos.dll loaded
!dumpstackobjects
PDB symbol for mscorwks.dll not loaded
OS Thread Id: 0xbb4 (2996)
ESP/REG Object Name
0012f0d4 012c2c10 System.Object[] (System.String[])
0012f20c 012c2c10 System.Object[] (System.String[])
0012f218 012c2c4c ObjectInternal.Product
0012f21c 012c2c64 ObjectInternal.Cateogry
0012f438 012c2c64 ObjectInternal.Cateogry
0012f43c 012c2c4c ObjectInternal.Product
0012f440 012c2c4c ObjectInternal.Product
0012f444 012c2c10 System.Object[] (System.String[])
0012f534 012c2c10 System.Object[] (System.String[])
0012f6e0 012c2c10 System.Object[] (System.String[])
0012f708 012c2c10 System.Object[] (System.String[])
!dumpobj 012c2c4c
Name: ObjectInternal.Product
MethodTable: 00933138
EEClass: 00931384
Size: 24(0x18) bytes
(C:\temp\ObjectInternal\ObjectInternal\bin\Debug\ObjectInternal.exe)
Fields:
MT Field Offset Type VT Attr Value Name
79332c4c 4000001 c System.Int32 1 instance 99 <Price>k__BackingField
79333520 4000002 10 System.Byte 1 instance 25 <Index>k__BackingField
79330a00 4000003 4 System.String 0 instance 012c2c20 <Name>k__BackingField
009331b0 4000004 8 ...Internal.Cateogry 0 instance 012c2c64 <Cat>k__BackingField
!dumpobj 012c2c20
Name: System.String
MethodTable: 79330a00
EEClass: 790ed64c
Size: 44(0x2c) bytes
(C:\WINDOWS\assembly\GAC_32\mscorlib\2.0.0.0__b77a5c561934e089\mscorlib.dll)
String: Super Product
Fields:
MT Field Offset Type VT Attr Value Name
79332c4c 4000096 4 System.Int32 1 instance 14 m_arrayLength
79332c4c 4000097 8 System.Int32 1 instance 13 m_stringLength
793316e0 4000098 c System.Char 1 instance 53 m_firstChar
79330a00 4000099 10 System.String 0 shared static Empty
>> Domain:Value 0015d370:012c1198 <<
79331630 400009a 14 System.Char[] 0 shared static WhitespaceChars
>> Domain:Value 0015d370:012c1790 <<
Physical memory layout of CLR objects:
We use !dumpobj to examine Product object instance, which is located at address: 0×012c2c4c. You can see that: field Name(String “Super Product”)’s address is 0×012c2c20, MethodTable is 0×79330a00. Field Cateogry’s address is 0×012c2c64 and MethodTable is 0×009331b0. Value types are directly stored as 0×63(99) and 0×19(25).
