在32位和64位的理解CLR对象的尺寸 [英] Understanding CLR object size between 32 bit vs 64 bit

查看:171
本文介绍了在32位和64位的理解CLR对象的尺寸的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想了解在32位和64位处理器的对象大小不同。比方说,我有一个简单的类

  MyClass类
{
    INT X;
    诠释Ÿ;
}
 

因此​​,一个32位计算机上的整数,是4个字节。如果我添加同步块到它(另外4个字节),对象的大小将是12个字节。为什么会显示16个字节?

0:000>做0x029d8b98
名称:ConsoleApplication1.Program + MyClass的
方法表:000e33b0
EEClass:000e149c
尺寸:16(0×10)个字节
 (C:\ MYTEMP \ ConsoleApplication1 \ ConsoleApplication1 \ BIN \ 86 \调试\ ConsoleApplication1.exe)
领域:
      MT字段偏移类型VT的Attr值名称
71972d70 4000003 4 System.Int32的1个实例0 X
71972d70 4000004 8 System.Int32的1个实例0是

在一个64位的机器,一个整数仍然是4字节唯一改变的是,同步块将是8个字节(如指针均为8个字节的64位机)。这意味着对象的大小将是16个字节。为什么会显示24个字节?

0:000>做0x00000000028f3c90
名称:ConsoleApplication1.Program + MyClass的
方法表:000007ff00043af8
EEClass:000007ff00182408
尺寸:24(为0x18)字节
 (C:\ MYTEMP \ ConsoleApplication1 \ ConsoleApplication1 \斌\调试\ ConsoleApplication1.exe)
领域:
              MT字段偏移类型VT的Attr值名称
000007fef4edd998 4000003 8 System.Int32的1个实例0 X
000007fef4edd998 4000004ÇSystem.Int32的1个实例0是

解决方案

的CLR可以自由地铺陈在内存中的对象,因为它认为合适的。这是一个实现细节。你不应该依赖于任何特定的布局。

你看到的差异是由于缺少类型句柄字段这也是CLR对象报头的一部分。此外,该字段可以被对齐字节边界


从<一个href="http://netinverse.com/devblogs/debugging/advanced-net-debugging-clr-objects-internal-structure/626/">Advanced净调试 - CLR对象的内部结构:

  

这是对象的CLR的内部结构是:

     

[DWORD:的SyncBlock] [DWORD:方法表指针] [DWORD:引用类型的指针] ... [数值类型字段值] ...

     

对象标题: [DWORD:的SyncBlock]
  的对象指针: [DWORD:方法表指针] [DWORD:引用类型的指针] ... [数值类型字段值] ...

     

每个对象是由一个ObjHeader pceded $ P $(在负偏移)。该ObjHeader的索引到的SyncBlock。


所以,你的目标很可能是布局是这样的:

86 的:(对齐到8字节)

  Syncblk类型句柄X Y
------------,------------ | ------------,----------- -  |
                         8月16日

64 的:(对齐到8字节)

         Syncblk类型句柄XY
------------------------- | ------------------------ -  | ------------,------------ |
                         8 16 24


另请参阅:钻成.NET框架内幕,看看如何在CLR创建运行时对象

I am trying to understand the object size difference between 32 bit and 64 bit processors. Let’s say I have a simple class

class MyClass   
{  
    int x;  
    int y;  
}  

So on a 32 bit machine, an integer is 4 bytes. If I add the Syncblock into it ( another 4 bytes), the object size will be 12 bytes. Why is it showing 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  

On a 64 bit machine, an integer is still 4 bytes the only thing changed is that Syncblock will be 8 bytes ( as pointers are 8 bytes on 64 bit machines). that mean the object size will be 16 bytes. Why is it showing 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  

The CLR is free to lay out objects in memory as it sees fit. It's an implementation detail. You should not rely on any specific layout.

The difference you see is due to the missing TypeHandle field which is also a part of the CLR object header. Additionally, the fields may be aligned to byte boundaries.


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

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.


So your object is likely laid out like this:

x86: (aligned to 8 bytes)

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

x64: (aligned to 8 bytes)

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


See also: Drill Into .NET Framework Internals to See How the CLR Creates Runtime Objects

这篇关于在32位和64位的理解CLR对象的尺寸的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆