手动编组结构内具有固定偏移量的固定大小字节数组会引发运行时异常吗?

问题描述 投票:0回答:1

目标是让以下结构在 C# (.net 8.0) 中工作

    [StructLayout(LayoutKind.Explicit, Size = 257, Pack = 1)]
    public struct MyFrame
    {
      [FieldOffset(0)] public byte valueA;
      [FieldOffset(1)] public byte valueB;
      [MarshalAs(UnmanagedType.ByValArray, SizeConst = 254)]
      [FieldOffset(2)] public byte[] valueArray;
      [FieldOffset(256)] public byte valueC;
    }

程序编译但在初始化期间抛出错误消息。

系统.TypeLoadException H结果=0x80131522 Message=无法从程序集“MyAssembly,Version=1.0.0.0,Culture=neutral,PublicKeyToken=null”加载类型“MyFrame”,因为它在偏移量 2 处包含一个对象字段,该对象字段未正确对齐或与非对象字段重叠。 来源=MyAssemböy 堆栈跟踪: 在 MyAssembly.MyClass..ctor() ...

我的理解是,使用 1 的包装尺寸应该是可能的。 如果我将 valueArray 从偏移量 8 处开始,它会编译并运行,但我想将其放在 2 处。

理想情况下,我也想将其扩展为这样

    [StructLayout(LayoutKind.Explicit, Size = 258, Pack = 1)]
    public struct MyFrame
    {
      [FieldOffset(0)] public byte valueA;
      [FieldOffset(1)] public byte valueB;
      [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.U1,  SizeConst = 254)]
      [FieldOffset(2)] public byte[] valueArray;
      [FieldOffset(256)] public byte valueC;
      [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.U1,  SizeConst = 257)]
      [FieldOffset(0)] public byte[] rawBytes;
    }

我该如何解决这个问题?

c# struct union marshalling
1个回答
0
投票

不能有重叠的引用类型对象,因此不能让数组与其他任何对象重叠。重叠是托管版本中的问题,而不是非托管版本中的问题。

它会在这里重叠,因为

FieldOffset
也会影响托管版本。

但是你不需要使用

LayoutKind.EXplicit
,你可以使用
Sequential

[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct MyFrame
{
    public byte valueA;
    public byte valueB;
    [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.U1, SizeConst = 254)]
    public byte[] valueArray;
    public byte valueC;
}
© www.soinside.com 2019 - 2024. All rights reserved.