【问题标题】:Struct is incorrectly aligned: System.TypeLoadException结构未正确对齐:System.TypeLoadException
【发布时间】:2014-12-01 05:29:00
【问题描述】:

我正在尝试在 C# 中创建以下结构,它是一个基于 C 的复杂结构,我尝试了大多数编组选项,但我总是得到“System.TypeLoadException”。

(附加信息:无法从程序集“WindowsFormsApplication1,Version=1.0.0.0,Culture=neutral,PublicKeyToken=null”加载类型“WindowsFormsApplication1.COMPLEX_STRUCT”,因为它包含偏移量 8 处的对象字段,该对象字段未正确对齐或重叠通过非对象字段。)

关于 IPV6_ADDR 结构,我尝试了 LayoutKind.Explicit 和 LayoutKind.Sequential, 和两者:

[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
public string Addr;

[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
public byte[] Addr;

我在 x64 机器上,但 IPV6_ADDR 结构对齐到 8 个字节,所以我不知道是什么问题。

[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct IPV4_ADDR
{
    public uint Addr;
    public uint SubnetNumBits;
};

[StructLayout(LayoutKind.Explicit, Pack = 1)]
public struct IPV6_ADDR
{
    [FieldOffset(0)]
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
    public string Addr;
    [FieldOffset(16)]
    public uint SubnetNumBits;
};

[StructLayout(LayoutKind.Explicit, Pack = 1)]
public struct COMPLEX_STRUCT
{
    [FieldOffset(0)]
    public byte A;

    [FieldOffset(1)]
    public byte B;

    [FieldOffset(2)]
    public byte C;

    [FieldOffset(3)]
    public byte D;

    [FieldOffset(4)]
    public byte E;

    [FieldOffset(8)]
    public IPV4_ADDR IPv4;

    [FieldOffset(8)]
    public IPV6_ADDR IPv6;

    [FieldOffset(28)]
    public ushort F;
}

我试图模仿的原始 C 结构:

typedef struct _IPV4_ADDR
{
    uint32_t Addr;
    uint32_t SubnetNumBits;
} IPV4_ADDR, *PIPV4_ADDR;

typedef struct _IPV6_ADDR
{
    uint8_t  Addr[16];
    uint32_t SubnetNumBits;
} IPV6_ADDR, *PIPV6_ADDR;

typedef struct _COMPLEX_STRUCT
{
    uint8_t A;
    uint8_t B;
    uint8_t C;
    uint8_t D;
    uint8_t E;
    uint8_t Rsvd[3];
    union {
        IPV4_ADDR IPv4;
        IPV6_ADDR IPv6;
    } u;
    uint16_t F;
} COMPLEX_STRUCT, *PCOMPLEX_STRUCT;

【问题讨论】:

  • @TyCobb 有。因为字符串是由 .NET 运行时管理的,所以不能将具有字符串的结构与在相同本地偏移处不具有字符串的结构重叠。
  • OK Thx,我真的不介意从 string 切换到 byte[] / char[],但我也试过了,还是不行
  • 我已将原始结构添加到您的问题中。请删除您的答案。

标签: c# struct marshalling typeloadexception structlayout


【解决方案1】:

在查看了您的原始结构并查看了 IPV4 和 IPV6 结构的其他实现之后,我发现其他实现使用byte[4] 作为 IPV4 的地址。

我不能保证结果是正确的,但是如果您能够将 IPV4 和 IPV6 更改为同时使用 byte[],那么您的错误就会消失。

你不能像你发现的那样混搭。我能想到的唯一其他选择是查看它是否允许您使用IntPtr 获取内存位置,然后使用Marshal.Copy 获取数据。

即使你让它们工作,但我不能保证你的结果是正确的。

【讨论】:

  • 我确实想联合它们,我正在转换一个具有 IPV4 和 IPV6 字段联合的 C 结构。我真的不介意从 string 切换到 byte[] / char[],但我也试过了,还是不行
  • @n00b 可能唯一可行的方法是将 byte[] 拆分为 2 ulongs。有一个 FieldOffset(0) 和 FieldOffset(8),然后在需要处理数据时将 2 个 long 合并为一个 byte[](结构上的方法)。
  • @n00b 您能否也展示一下您试图模仿的实际结构?我开始认为您的 IPVx 结构应该使用 IntPtr 而不是 unintstring
  • 感谢@TyCobb,下面的原始结构
猜你喜欢
  • 2013-12-12
  • 2021-11-16
  • 2017-07-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-19
  • 1970-01-01
相关资源
最近更新 更多