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

为何C#认为该非托管结构体存在字段重叠?

问题原因与解决方案

错误根源

你遇到的TypeLoadException核心原因是:byte[]是引用类型(托管对象),即使添加了MarshalAs属性,该属性仅作用于非托管代码的封送逻辑,不会改变它在托管内存中的存储形式。

在托管内存里,byte[]本质是一个指针(64位系统占8字节,32位系统占4字节),而非你预期的13字节数组内容。你通过FieldOffset(4)指定它的起始位置,再加上指针自身的字节数,会直接和后续的transmissionNumber(FieldOffset(17))字段产生内存重叠,同时CLR对引用类型字段有严格的对齐要求,这就触发了类型加载错误。

两种可行解决方案

方案1:使用unsafe固定数组(推荐用于严格匹配非托管内存布局)

将byte[]替换为fixed字节数组,这样数组内容会直接嵌入结构体的内存中,完全符合你预期的18字节布局:

[StructLayout(LayoutKind.Explicit, Size = 18, Pack = 1, CharSet = CharSet.Ansi)]
unsafe struct FlexTransmission
{
    [FieldOffset(0)]
    public UInt32 transmissionTime;
    
    [FieldOffset(4)]
    public fixed byte flexData[13]; // 直接嵌入结构体的13字节连续内存
    
    [FieldOffset(17)]
    public byte transmissionNumber;
}

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

方案2:改用顺序布局(无需unsafe代码)

如果不需要显式指定FieldOffset,改用LayoutKind.Sequential,配合MarshalAs确保互操作时的封送正确性:

[StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi, Size = 18)]
struct FlexTransmission
{
    public UInt32 transmissionTime;
    
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 13)]
    public byte[] flexData;
    
    public byte transmissionNumber;
}

这种方式下,托管内存中flexData仍是引用类型,但在与非托管代码交互时,CLR会按照你指定的13字节数组进行封送,不会触发类型加载错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 21:03:23