Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Marshal.SizeOf(typeof(IntPtr)) vs sizeof(IntPtr)

Tags:

c#

.net

I know how fundamentally different Marshal.SizeOf() and sizeof() are. But in the case of an IntPtr, won't they both always return exactly the same thing regardless of CPU architecture?

like image 378
cogumel0 Avatar asked Jan 05 '23 19:01

cogumel0


1 Answers

For one thing, there's the primitive types:

| x64 | x86
| Marshal. | Marshal.
Primitive | SizeOf<T>() sizeof(T) | SizeOf<T>() sizeof(T)
========= | =========== =========== | =========== ===========
Boolean | 4 <-> 1 | 4 <-> 1
Byte | 1 1 | 1 1
SByte | 1 1 | 1 1
Int16 | 2 2 | 2 2
UInt16 | 2 2 | 2 2
Int32 | 4 4 | 4 4
UInt32 | 4 4 | 4 4
Int64 | 8 8 | 8 8
UInt64 | 8 8 | 8 8
IntPtr | 8 8 <-> 4 4
UIntPtr | 8 8 <-> 4 4
Char | 1 <-> 2 | 1 <-> 2
Double | 8 8 | 8 8
Single | 4 4 | 4 4

Beyond this, for struct (ValueType) instances in .NET there can be significant differences between the internal managed layout and the marshaling image, both in total size and also the field layout ordering. The latter is true even for so-called formatted classes.[1]

It's rare to actually need information about the actual managed struct layout, and in fact .NET goes to great lengths in trying to make it undiscoverable. You also can't influence the internal layout of structs, and that's precisely why the Marshal layer provides the ability to specifically declare whatever layout you need for interop.

Here's one use case for needing to know the true size of a struct's runtime memory image: Let's say you are using managed arrays of structs for some kind of storage blob concept and you want each chunk (array, that is) to stay under a fixed total allocation size, say ~84,800 bytes--obviously in this case to stay out of the LOH. You want this storage class to be a generic class, parameterized with an arbitrary ValueType type which defines the 'records' or table entries. To determine the number of structs that can go into each managed array chunk, you'd need to discover the true size of the structure given at runtime, so you can divide 84,800 by that value.

For a more detailed examination of the differences that can arise between marshaling versus managed-internal struct layout, padding, and size, please see my extended answer to "How do I check the number of bytes consumed by a structure?"



[1.] "A formatted class is a reference type whose layout is specified by the StructLayoutAttribute attribute, as either LayoutKind.Explicit or LayoutKind.Sequential."
https://msdn.microsoft.com/en-us/library/2zhzfk83(v=vs.110).aspx

like image 71
Glenn Slayden Avatar answered Jan 13 '23 06:01

Glenn Slayden