Skip to content

Marshalling record via PtrToStructure with two levels of inheritance shifts field offset #50764

@SmartK8

Description

@SmartK8

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.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions