2010-09-28 21 views
14

Estoy tratando de comprender la diferencia de tamaño de objeto entre procesadores de 32 bits y 64 bits. Digamos que tengo una clase simpleComprensión del tamaño de objeto CLR entre 32 bit frente a 64 bit

class MyClass 
{ 
    int x; 
    int y; 
} 

Así que en una máquina de 32 bits, es un número entero de 4 bytes. Si agrego el Syncblock en él (otros 4 bytes), el tamaño del objeto será de 12 bytes. ¿Por qué muestra 16 bytes?

 
0:000> !do 0x029d8b98 
Name: ConsoleApplication1.Program+MyClass 
MethodTable: 000e33b0 
EEClass: 000e149c 
Size: 16(0x10) bytes 
(C:\MyTemp\ConsoleApplication1\ConsoleApplication1\bin\x86\Debug\ConsoleApplication1.exe) 
Fields: 
     MT Field Offset     Type VT  Attr Value Name 
71972d70 4000003  4   System.Int32 1 instance  0 x 
71972d70 4000004  8   System.Int32 1 instance  0 y 

En una máquina de 64 bits, un número entero es todavía 4 bytes lo único cambiado es que Syncblock será de 8 bytes (como punteros son 8 bytes en equipos de 64 bits). eso significa que el tamaño del objeto será de 16 bytes. ¿Por qué muestra 24 bytes?

 
0:000> !do 0x00000000028f3c90 
Name: ConsoleApplication1.Program+MyClass 
MethodTable: 000007ff00043af8 
EEClass: 000007ff00182408 
Size: 24(0x18) bytes 
(C:\MyTemp\ConsoleApplication1\ConsoleApplication1\bin\Debug\ConsoleApplication1.exe) 
Fields: 
       MT Field Offset     Type VT  Attr   Value Name 
000007fef4edd998 4000003  8   System.Int32 1 instance    0 x 
000007fef4edd998 4000004  c   System.Int32 1 instance    0 y 

Respuesta

24

El CLR es libre de colocar objetos en la memoria como lo considere oportuno. Es un detalle de implementación. No debe confiar en ningún diseño específico.

La diferencia que ve se debe al campo TypeHandle que falta, que también forma parte del encabezado del objeto CLR. Además, los campos pueden estar alineados con los límites de bytes.


De Advanced .Net Debugging - CLR Object’s Internal Structure:

estructura interna CLR de un objeto es:

[DWORD: SyncBlock] [DWORD: MethodTable Puntero] [DWORD: Referencia tipo de puntero] ... [Valor de Valor campo tipo] ...

objeto de encabezado: [DWORD: SyncBlock]
Puntero a objeto: [DWORD: puntero de tipo de referencia] ... [Valor del campo Tipo de valor] ...

Todos los objetos van precedidos de un ObjHeader (en un desplazamiento negativo). El ObjHeader tiene un índice para un SyncBlock.


Así que su objeto es probable diseñada como esto:

x 86: (alineado a 8 bytes)

 
    Syncblk  TypeHandle  X   Y 
------------,------------|------------,------------| 
         8       16 

x64: (alineado a 8 bytes)

 
     Syncblk     TypeHandle    X   Y 
-------------------------|-------------------------|------------,------------| 
         8       16      24 

Ver también: Drill Into .NET Framework Internals to See How the CLR Creates Runtime Objects

0

Los objetos tienen algo de sobrecarga más allá de las variables miembro. En las implementaciones de 32 bits de .NET, la sobrecarga de asignación parece ser de 12 bytes. Según recuerdo, son 16 bytes en el tiempo de ejecución de 64 bits.

Además, las asignaciones de objetos se alinean en el siguiente límite de 8 bytes.

+0

Alineado o no, el tamaño aún debe reflejar el tamaño real del objeto. El relleno solo contaría para el tamaño si fuera entre miembros, lo que no parece ser el caso aquí. – cHao

+0

Los detalles sobre cualquier sobrecarga fuera del objeto en sí no son realmente relevantes en este caso. La mayor parte de esa sobrecarga está en tablas de objetos en el tiempo de ejecución, no en el objeto. – cHao

0

Me parece que cualquier objeto debería tener algún tipo de puntero a su clase. Eso representaría sus 4 u 8 bytes adicionales.

Sin embargo, el diseño de un objeto es realmente una implementación. Si le importa el diseño, existen atributos diseñados para decirle explícitamente a .net dónde y cómo quiere que se ubiquen los miembros. Consulte StructLayoutAttribute.

7

El bloque de sincronización se encuentra en un desplazamiento negativo desde el puntero del objeto. El primer campo en el desplazamiento 0 es el puntero de la tabla de métodos, 8 bytes en x64. Entonces en x86 es SB + MT + X + Y = 4 + 4 + 4 + 4 = 16 bytes. El índice de bloque de sincronización aún tiene 4 bytes en x64. Pero el encabezado del objeto también participa en el montón recogido de basura, actuando como un nodo en una lista vinculada después de que se libera. Esto requiere un puntero hacia adelante y hacia atrás, cada 8 bytes en x64, por lo que requiere 8 bytes antes del puntero del objeto. 8 + 8 + 4 + 4 = 24 bytes.

Cuestiones relacionadas