我正在尝试在这篇msdn文章中创建以下结构。我正在尝试学习整个FieldOffset,但不知道从哪里开始。
我基本上做了类似的事。
[StructLayout(LayoutKind.Explicit, Size=12)]
public struct DHCP_OPTION_DATA_ELEMENT {
[FieldOffset(0)]
public DHCP_OPTION_DATA_TYPE OptionType;
[FieldOffset(4)]
public byte ByteOption;
[FieldOffset(4)]
public uint WordOption;
[FieldOffset(4)]
public UInt32 DWordOption;
[FieldOffset(4)]
public UInt32 DWordDWordOption;
[FieldOffset(4)]
public uint IpAddressOption;
[FieldOffset(4)]
public IntPtr StringDataOption;
[FieldOffset(4)]
public DHCP_BINARY_DATA BinaryDataOption;
[FieldOffset(4)]
public DHCP_BINARY_DATA EncapsulatedDataOption;
[FieldOffset(4)]
public string Ipv6AddressDataOption;
}
然而,它在我面前咆哮说明了以下异常。
it contains an object field at offset 4 that is incorrectly aligned or
overlapped by a non-object field.
答案 0 :(得分:2)
将其视为IntPtr,而不是字符串。
但是,在使用IntPtr时,请确保自己完成清理,因为现在您将使用非托管内存,因此GC不会帮助您,导致每个内存泄漏你传递这个结构的时间。
你很可能想要使用Marshal.PtrToStringUni函数,正如shf301在另一个答案中建议的那样。
答案 1 :(得分:1)
错误
它包含偏移4处的对象字段,该字段未正确对齐或 由非对象字段重叠。
是由于非对象(blittable)类型(例如Uint32
)与对象类型(非blittable)重叠。编组人无法处理。 marhshaler不知道联合的哪个字段是有效的(因为它不知道如何解码OptionType
所以它不知道它是否应该编组字符串值或整数值。试图编组一个字符串的整数值会导致崩溃(因为整数值不会指向有效的字符串),因此编组器抛出异常而不是让您崩溃。
因此,您必须手动编组字符串,方法是将其定义为IntPtr
并使用Marshal.PtrToStringUni()或Marshal.PtrToStringAnsi()。
您也可能遇到与DHCP_BINARY_DATA相同的问题。
答案 2 :(得分:0)
您有以下代码:
[FieldOffset(4)]
public string Ipv6AddressDataOption;
String是引用类型(对象),其他字段是值类型(非对象)。因此,您必须更改Ipv6AddressDataOption
的偏移量。