You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET 8手动编组结构体固定偏移字节数组触发异常如何解决?

问题解决思路与修正代码

错误根源

你碰到的System.TypeLoadException本质原因是:byte[]是托管引用类型,在结构体中存储的是指向数组数据的指针(64位系统占8字节)。CLR对引用类型字段有两个强制要求:

  1. 必须满足平台对齐规则(64位系统下是8字节对齐),偏移2显然不符合;
  2. 引用类型字段的内存区域不能与值类型字段重叠,而你的valueArray指针会覆盖后续valueC的内存位置。

Pack=1只影响非托管值类型的对齐,对托管引用类型的指针无效,所以靠调整Pack无法解决问题。

修正方案:使用固定大小缓冲区(Fixed Buffer)

固定大小缓冲区是值类型,会直接嵌入结构体的内存布局中,不需要指针,完全适配显式布局的要求。需要开启项目的不安全代码支持(项目属性→生成→勾选“允许不安全代码”)。

基础版结构体修正代码

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

联合版结构体修正代码

注意:原代码中Size=258是错误的,rawBytes长度257字节刚好覆盖整个结构体(偏移0到256),所以结构体总大小应为257:

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

固定缓冲区的操作方法

如果需要将固定缓冲区转换为更易用的Span<byte>或byte[],可以借助MemoryMarshal:

var frame = new MyFrame();

// 将valueArray转为Span<byte>
unsafe
{
    Span<byte> arraySpan = MemoryMarshal.CreateSpan(ref frame.valueArray[0], 254);
    // 直接操作arraySpan即可修改结构体内存
}

// 将rawBytes转为Span<byte>
unsafe
{
    Span<byte> rawSpan = MemoryMarshal.CreateSpan(ref frame.rawBytes[0], 257);
}

内容的提问来源于stack exchange,提问作者Axel M

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 09:20:22