-
Notifications
You must be signed in to change notification settings - Fork 5.2k
Description
Description
I've encountered this situation. I have the code below and after executed, the result.Value is { 0x02, 0x03, 0x00 } instead of contents of data. Note: freeing memory stripped off for brevity.
public static void Main()
{
Byte[] data = { 0x01, 0x02, 0x03 };
GCHandle memory = GCHandle.Alloc(data, GCHandleType.Pinned);
IntPtr handle = memory.AddrOfPinnedObject();
FinalRecord result = (FinalRecord) Marshal.PtrToStructure(handle, typeof(FinalRecord));
}
[StructLayout(LayoutKind.Sequential)]
public abstract record BaseRecord;
[StructLayout(LayoutKind.Sequential)]
public abstract record InheritedRecord : BaseRecord;
[StructLayout(LayoutKind.Sequential)]
public sealed record FinalRecord : InheritedRecord
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
private readonly Byte[] Value;
}
But if I remove one level of inheritance (below), it works correctly again: result.Value is { 0x01, 0x02, 0x03 }. I've digged a bit, but only thing I've found is that Marshal.OffsetOf the field is set to 0 when it's working and to 1 (for unknown reason) when it's not. As far as I know abstract/sealed/readonly has no effect on this. Only three (or more) levels of inheritance. It doesn't get worse with 4 levels (still shifted by 1 byte). Happens on both x86/x64 builds.
[StructLayout(LayoutKind.Sequential)]
public record InheritedRecord; // : BaseRecord;
Configuration
Which version of .NET is the code running on? .NET 5.0.4
What OS and version, and what distro if applicable? Windows 10 20H2 (19042.906)
What is the architecture (x64, x86, ARM, ARM64)? x64
Do you know whether it is specific to that configuration? No, I don't. But I don't think it is.