2010-04-11 8 views
5

È a mia conoscenza che tutte le istanze di oggetti .NET iniziano con un 'intestazione dell'oggetto da 8 byte: un blocco di sincronizzazione (puntatore a 4 byte in una tabella SynchTableEntry) e un handle di tipo (puntatore a 4 byte nella tabella dei metodi dei tipi).Non vedere il blocco di sincronizzazione nel layout degli oggetti

Non lo vedo nelle finestre di memoria del debugger di VS 2010 RC (CLR 4.0).

Ecco una semplice classe che genererà un'istanza di 16 byte, meno l'intestazione dell'oggetto.

class Program 
{ 
    short myInt = 2; // 4 bytes 
    long myLong = 3; // 8 bytes 
    string myString = "aString"; // 4 byte object reference 

    // 16 byte instance 

    static void Main(string[] args) 
    { 
     new Program(); 
     return; 
    } 
} 

Un dump di oggetto SOS mi dice che la dimensione totale dell'oggetto è di 24 byte. Ciò ha senso. La mia istanza da 16 byte più un'intestazione di oggetto da 8 byte.

!DumpObj 0205b660 
Name:  Offset_Test.Program 
MethodTable: 000d383c 
EEClass:  000d13f8 
Size:  24(0x18) bytes 
File:  C:\Users\Bob\Desktop\Offset_Test\Offset_Test\bin\Debug\Offset_Test.exe 
Fields: 
     MT Field Offset     Type VT  Attr Value Name 
632020fc 4000001  10   System.Int16 1 instance  2 myInt 
632050d8 4000002  4   System.Int64 1 instance  3 myLong 
631fd2b8 4000003  c   System.String 0 instance 0205b678 myString

Ecco il ricordo grezzo:

0x0205B660 000d383c 00000003 00000000 0205b678 00000002 ...

e qui ci sono alcune annotazioni:

offset 0 000d383c ;TypeHandle (pointer to MethodTable), 4 bytes 
offset 4 00000003 00000000 ;myLong, 8 bytes 
offset 12 0205b678 ;myString, 4 byte reference to address of "myString" on GC Heap 
offset 16 00000002 ;myInt, 4 bytes

Il mio scopo inizia un indirizzo 0x0205B660. Ma posso contare solo 20 byte, il tipo handle e i campi istanza. Non c'è alcun segno di un puntatore del blocco di sincronizzazione. La dimensione dell'oggetto è riportata come 24 byte, ma il debugger sta mostrando che occupa solo 20 byte di memoria.

Sto leggendo Drill Into .NET Framework Internals to See How the CLR Creates Runtime Objects e mi aspetto che i primi 4 byte del mio oggetto siano un puntatore a blocco di sincronizzazione azzerato, come mostrato nella Figura 8 di tale articolo. Certo, questo è un articolo su CLR 1.1.

Mi stavo chiedendo se la differenza tra ciò che sto vedendo e ciò che questo articolo ha riportato è un cambiamento nella visualizzazione del layout di oggetti del debugger, o nel modo in cui il CLR espone gli oggetti nelle versioni successive alla 1.1 .

In ogni caso, qualcuno può rendere conto dei miei 4 byte mancanti?

risposta

8

Credo che il blocco di sincronizzazione sia "dietro" il puntatore dell'oggetto nella memoria. In questo modo una variabile di riferimento punta direttamente alla tabella del metodo. Quindi, per il tuo oggetto all'indirizzo 0x0205B660, il blocco di sincronizzazione sarà all'indirizzo 0x0205B65C.

+2

Grazie CD. Hai ragione. 0x0205B660-0x4 mi porta all'intestazione dell'oggetto che contiene un indice di blocco di sincronizzazione, se ne viene impostato uno. Così ho bloccato il mio oggetto e ho eseguito: ! Syncblk 0x1 per ottenere il primo indice nella tabella dei blocchi di sincronizzazione. L'output mi fornisce l'indice del blocco di sincronizzazione, l'indirizzo e il proprietario (il mio oggetto). Quindi un riferimento a un oggetto fa riferimento al campo del tipo handle e (oggetto reference - 0x4) punta all'intestazione dell'oggetto, che contiene tutti i tipi di informazioni, a seconda del flusso di esecuzione. Ho appena preso "Advanced .NET Debugging" di Mario Hewardt e tratta questa roba in dettaglio. Grazie ancora. – user314045

Problemi correlati