Search code examples
c#marshallinglayoutkind.explicit

Marshalling LayoutKind.Explicit struct with overlapping fails in Release build


I have a struct which has a non-overlapping field reported as overlapped.

[FieldOffset(8)]
Int32 X;

[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
[FieldOffset(12)]
string Y;

[FieldOffset(28)]
int Z;

The reported error is:

Could not load type 'XXX' ... it contains an object field at offset 12 that is incorrectly aligned or overlapped by a non-object field.

It occurs only in Release configuration (TRACE, DEBUG flags and unsafe code are enabled, optimization is turned off), guessing - what happens to it?

UPD: thanks to @svick. Confirmed that x64 build is not what one wants for marshalling.


Solution

  • First, Release configuration has nothing to do with this. What affects it is Platform Target: if you set it to x64, you will get this exception, but if you set it to x86, it will work fine.

    I think the reason for this behavior is that FieldOffset is used to specify the layout of the struct in the managed memory (even if the documentation doesn't say this), but MarshalAs is not used in managed memory.

    Because of this, the object in managed memory contains a reference at offset 12. And since all references have to be aligned in .Net (to 4 bytes in 32-bit application and to 8 bytes in 64-bit), you get the exception if you run your application as 64-bit.

    So, the problem is not that you have overlapped fields, it's the other part of the error message: the field is incorrectly aligned.

    The easy workaround is to compile the application as x86. If that's not possible for you, I'm not sure how to fix this.