Understanding CLR object size between 32 bit vs 64 bit

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


The sync block sits at a negative offset from the object pointer. The first field at offset 0 is the method table pointer, 8 bytes on x64. So on x86 it is SB + MT + X + Y = 4 + 4 + 4 + 4 = 16 bytes. The sync block index is still 4 bytes in x64. But the object header also participates in the garbage collected heap, acting as a node in a linked list after it is released. That requires a back and a forward pointer, each 8 bytes in x64, thus requiring 8 bytes before the object pointer. 8 + 8 + 4 + 4 = 24 bytes.


Objects have some overhead beyond the member variables. In 32-bit implementations of .NET, the allocation overhead appears to be 12 bytes. As I recall, it's 16 bytes in the 64 bit runtime.

In addition, object allocations are aligned on the next 8 byte boundary.


Seems to me, any object should have some kind of pointer to its class. That'd account for your extra 4 or 8 bytes.

The layout of an object is really an implementation thing, though. If you care about the layout, there are attributes designed to explicitly tell .net where and how you want the members positioned. Check out StructLayoutAttribute.


Comments

  1. Amos

    • 2018/1/18

    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.

  2. Koroveshi

    • 2017/2/27

    Objects have some overhead beyond the member variables. In 32-bit implementations of .NET, the allocation overhead appears to be 12 bytes. As I recall, it's 16 bytes in the 64 bit runtime. In addition, object allocations are aligned on the next 8 byte boundary.

  3. Callan

    • 2019/11/16

    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; } 

  4. Alfred

    • 2017/4/19

    Basically, a 32-bit app can only load 32-bit dlls, and a 64-bit app can only load 64-bit dlls. But what about apps compiled as “Any CPU”? In that case, you can only load dlls matching whatever bitness you’re currently running as.

  5. Landyn

    • 2015/11/4

    The CLR is free to place objects in memory at its discretion. This is an implementation detail. You should not rely on any particular layout.

  6. Jagger

    • 2021/4/22

    .net - Understanding CLR object size between 32 bit vs 64 bit . 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,…

  7. Bear

    • 2019/11/16

    32 bit processor and 64 bit OS please do help me to understand maximum memory size for CLR object in latest Framework version above 4.5.

  8. Nelson

    • 2016/6/18

    When it comes to computers, the difference between 32-bit and a 64-bit is all about processing power. Computers with 32-bit processors are older, slower, and less secure, while a 64-bit processor is newer, faster, and more secure.

  9. Marku

    • 2021/6/12

    NET Framework 4 or later versions also run under WOW64 on 64-bit systems. Visual Studio installs the 32-bit version of the CLR on an x86 

  10. Spencer

    • 2019/10/19

    Here’s the key difference: 32-bit processors are perfectly capable of handling a limited amount of RAM (in Windows, 4GB or less), and 64-bit processors can utilize much more.

  11. Evans

    • 2015/3/15

    IntPtr.Size will be 4. This isn't a way to tell the bitness of your OS, just the bitness of your running CLR process. Here's 

  12. Bear

    • 2015/1/14

    64-bit vs 32-bit. Maoni. May 15th, 2007. As 64-bit machines become more common, the problems we need to solve also evolve. In this post I’d like to talk about what it means for the GC and the applications’ memory usage when we move from 32-bit to 64-bit. One big limitation of 32-bit is the virtual memory address space – as a user mode process you get 2GB, and if you use large address aware you get 3GB.

  13. Judson

    • 2020/10/9

    This article determines the length of an object's instance and a CLR object as well as differences between 32-bit and 64-bit systems for 

  14. Marquis

    • 2018/9/29

    Is there an object of size 0? No object is less than 12 bytes in 32 bits, or 24 bytes in 64 bits. The object must have at least one 

  15. Ezekiel

    • 2015/2/22

    On a 32-bit system, the header is 8 bytes long, and if you're running in a 64-bit process, it takes 16 bytes. So an object that contained just one field of 

  16. Ares

    • 2017/11/3

    For instance, a 32 bit system cannot have more than 4 GB of physical memory. in a 64bit Windows, or to a 3GB address space if running in a 32bit Windows 

Comments are closed.

Recent Posts