2010-09-28 45 views
14

Tôi đang cố gắng hiểu sự khác biệt về kích thước đối tượng giữa bộ xử lý 32 bit và 64 bit. Giả sử tôi có một lớp đơn giảnTìm hiểu kích thước đối tượng CLR giữa 32 bit so với 64 bit

class MyClass 
{ 
    int x; 
    int y; 
} 

Vì vậy, trên máy 32 bit, số nguyên là 4 byte. Nếu tôi thêm Syncblock vào nó (4 byte khác), kích thước đối tượng sẽ là 12 byte. Tại sao nó hiển thị 16 byte?

 
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 

Trên máy 64 bit, một số nguyên vẫn là 4 byte, điều duy nhất được thay đổi là Syncblock sẽ là 8 byte (như con trỏ là 8 byte trên máy 64 bit). điều đó có nghĩa là kích thước đối tượng sẽ là 16 byte. Tại sao nó hiển thị 24 byte?

 
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 

Trả lời

24

CLR là miễn phí để bố trí các đối tượng trong bộ nhớ khi nó khớp. Đó là một chi tiết thực hiện. Bạn không nên dựa vào bất kỳ bố cục cụ thể nào.

Sự khác biệt bạn thấy là do trường TypeHandle bị thiếu cũng là một phần của tiêu đề đối tượng CLR. Ngoài ra, các trường có thể được liên kết với các ranh giới byte.


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

cấu trúc bên trong CLR An đối tượng là:

[DWORD: SyncBlock] [DWORD: MethodTable Pointer] [DWORD: Reference loại con trỏ] ... [Giá trị của giá trị gia tăng loại field] ...

Object Tiêu đề: [DWORD: SyncBlock]
Con trỏ đối tượng: [DWORD: Con trỏ MethodTable] [DWORD: Con trỏ kiểu tham chiếu]… [Giá trị của trường Loại giá trị]…

Mọi đối tượng được bắt đầu bởi một ObjHeader (ở độ lệch âm). ObjHeader có chỉ mục cho SyncBlock.


Vì vậy, đối tượng của bạn có khả năng đặt ra như thế này:

x86: (liên kết tới 8 byte)

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

x64: (liên kết tới 8 byte)

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

Xem thêm: Drill Into .NET Framework Internals to See How the CLR Creates Runtime Objects

0

Đối tượng có một số chi phí ngoài các biến thành viên. Trong triển khai 32-bit của .NET, chi phí phân bổ dường như là 12 byte. Khi tôi nhớ lại, nó là 16 byte trong thời gian chạy 64 bit.

Ngoài ra, phân bổ đối tượng được căn chỉnh trên ranh giới 8 byte tiếp theo.

+0

Đã được căn chỉnh hay không, kích thước vẫn phải phản ánh kích thước thực của đối tượng. Phần đệm sẽ chỉ được tính vào kích thước nếu nó nằm giữa các thành viên, mà dường như không phải là trường hợp ở đây. – cHao

+0

Các chi tiết về bất kỳ chi phí nào bên ngoài đối tượng không thực sự có liên quan trong trường hợp này. Hầu hết các chi phí trên là trong các bảng đối tượng trong thời gian chạy, không phải trên đối tượng. – cHao

0

Dường như với tôi, bất kỳ đối tượng nào cũng có một số loại con trỏ đến lớp của nó. Điều đó sẽ chiếm thêm 4 hoặc 8 byte của bạn.

Bố cục của một đối tượng thực sự là một điều thực hiện. Nếu bạn quan tâm đến cách bố trí, có các thuộc tính được thiết kế để nói rõ ràng .net ở đâu và cách bạn muốn các thành viên được định vị. Kiểm tra StructLayoutAttribute.

7

Khối đồng bộ hóa nằm ở độ lệch âm từ con trỏ đối tượng. Trường đầu tiên tại offset 0 là con trỏ của bảng phương thức, 8 byte trên x64. Vì vậy, trên x86 nó là SB + MT + X + Y = 4 + 4 + 4 + 4 = 16 byte. Chỉ mục khối đồng bộ hóa vẫn là 4 byte trong x64. Nhưng tiêu đề đối tượng cũng tham gia vào đống rác thu thập được, hoạt động như một nút trong một danh sách liên kết sau khi nó được phát hành. Điều đó yêu cầu một con trỏ lùi và tiến, mỗi 8 byte trong x64, do đó yêu cầu 8 byte trước con trỏ đối tượng. 8 + 8 + 4 + 4 = 24 byte.

Các vấn đề liên quan