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

C#含数组的显式布局结构体导致测试异常求助

解决C#显式布局结构体含数组导致测试崩溃的问题

问题根源

你代码里的核心错误是把引用类型(byte[])和值类型(uint)放在了同一个FieldOffset上。在CLR中,引用类型存储的是指向托管堆对象的指针(32位系统占4字节,64位占8字节),而uint是直接存储4字节值的值类型,强行让两者内存重叠会直接破坏CLR的内存结构,引发未定义行为——这就是测试运行器崩溃、返回异常退出码的原因。把数组换成单个byte(值类型)就正常,也验证了这一点:只有同类型或内存布局兼容的值类型,才能安全地在显式布局结构体中重叠。

可行解决思路

方案1:使用固定大小缓冲区(需unsafe代码)

用fixed关键字定义固定大小的字节数组,这样数组会直接嵌入结构体的内存中(而非存储引用),可以和uint安全重叠:

[StructLayout(LayoutKind.Explicit)]
internal unsafe struct StructA
{
    [FieldOffset(0)]
    public fixed byte Values[4]; // 固定大小缓冲区,直接占用4字节内存

    [FieldOffset(0)]
    public uint Code;

    public StructA(uint code)
    {
        Code = code;
    }

    // 辅助方法:将固定缓冲区转为普通byte[]
    public byte[] GetValues()
    {
        byte[] result = new byte[4];
        fixed (byte* ptr = Values)
        {
            Marshal.Copy((IntPtr)ptr, result, 0, 4);
        }
        return result;
    }

    // 辅助方法:用普通byte[]设置缓冲区值
    public void SetValues(byte[] values)
    {
        if (values.Length != 4) throw new ArgumentException("数组长度必须为4");
        fixed (byte* ptr = Values)
        {
            Marshal.Copy(values, 0, (IntPtr)ptr, 4);
        }
    }
}

注意:需要在项目属性的“生成”选项中勾选允许不安全代码才能编译。

方案2:用BitConverter手动转换(无需unsafe)

如果不想用unsafe代码,直接去掉显式布局,通过托管代码的类型转换实现需求:

internal struct StructA
{
    public uint Code;

    public StructA(uint code)
    {
        Code = code;
    }

    public StructA(byte[] values)
    {
        if (values.Length != 4) throw new ArgumentException("数组长度必须为4");
        Code = BitConverter.ToUInt32(values, 0);
    }

    public byte[] ToByteArray()
    {
        return BitConverter.GetBytes(Code);
    }
}

这个方案完全避免了内存重叠问题,更安全,也不需要额外的项目配置。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 02:32:15