Marshal.PtrToStructure 中的访问冲突
我正在尝试反序列化一个结构,但在 PtrToStructure 中遇到 AV 异常。唯一的问题是这是一个可变长度结构,因此我需要在反序列化之前调整长度。这是我的代码,有什么明显的错误吗?该结构仅包含整数/短/字节数组,没有什么花哨的。
传入的数据是 374 字节,我需要调整它以匹配 576 字节的数据结构。基本上,传入数据包的最后一个字段比最大可能字段短,这是正常的。
public static ... FromByteArray(byte[] receivedData)
{
int rawsize = Marshal.SizeOf(typeof(MyPacket));
// allocate a new buffer of the maximum size, to help deserialization
byte[] newBuffer = new byte[rawsize];
Array.Copy(receivedData, newBuffer, receivedData.Length);
IntPtr buffer = Marshal.AllocHGlobal(rawsize);
Marshal.Copy(newBuffer, 0, buffer, rawsize);
/// CRASHES ON NEXT LINE
MyPacketDefinition def = (MyPacketDefinition ) Marshal.PtrToStructure(buffer, typeof(MyPacketDefinition ));
Marshal.FreeHGlobal(buffer);
//...
}
我的结构看起来像这样:
[StructLayout (LayoutKind.Explicit, Pack=1, Size=576, CharSet=CharSet.Ansi)]
public struct MyPacket
{
[FieldOffset(0)]
public System.Byte Type;
.
. // a few more INT/SHORT fields
.
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
[FieldOffset(28)] public System.Byte[] Address;
[MarshalAs(UnmanagedType.LPStr, SizeConst=64)]
[FieldOffset(44)] public System.String Name;
[MarshalAs(UnmanagedType.LPStr, SizeConst = 128)]
[FieldOffset(108)] public System.String SystemData;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 340)]
[FieldOffset(236)] public System.Byte[] Options;
}
最后一个参数(选项)是最大 340 字节的可变长度字段(通常更短)
I am trying to deserialize a structure, and I'm getting an AV exception in PtrToStructure. The only wrinkle is that this is a variable length structure, so I need to adjust the length before deserializing. Here's my code, is there anything obviously wrong? The structure contains only integer/short/byte arrays, nothing fancy.
the incoming data is 374 bytes, and I need to adjust it to match the 576 bytes data structure. Basically the incoming packet has a shorter last field than the max possible, which is normal.
public static ... FromByteArray(byte[] receivedData)
{
int rawsize = Marshal.SizeOf(typeof(MyPacket));
// allocate a new buffer of the maximum size, to help deserialization
byte[] newBuffer = new byte[rawsize];
Array.Copy(receivedData, newBuffer, receivedData.Length);
IntPtr buffer = Marshal.AllocHGlobal(rawsize);
Marshal.Copy(newBuffer, 0, buffer, rawsize);
/// CRASHES ON NEXT LINE
MyPacketDefinition def = (MyPacketDefinition ) Marshal.PtrToStructure(buffer, typeof(MyPacketDefinition ));
Marshal.FreeHGlobal(buffer);
//...
}
My structure looks something like this:
[StructLayout (LayoutKind.Explicit, Pack=1, Size=576, CharSet=CharSet.Ansi)]
public struct MyPacket
{
[FieldOffset(0)]
public System.Byte Type;
.
. // a few more INT/SHORT fields
.
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
[FieldOffset(28)] public System.Byte[] Address;
[MarshalAs(UnmanagedType.LPStr, SizeConst=64)]
[FieldOffset(44)] public System.String Name;
[MarshalAs(UnmanagedType.LPStr, SizeConst = 128)]
[FieldOffset(108)] public System.String SystemData;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 340)]
[FieldOffset(236)] public System.Byte[] Options;
}
With the last parameter (Option) being a variable length field of maximum 340 bytes (normally shorter)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
有点晚了,但是……
为了在结构体内部使用 C# 编组数组,您必须将它们声明为“固定”,否则它们只是指向托管内存的指针,这会造成混乱。
值得注意的是,出于某种原因,“修复”是一个不安全的选项,需要您将代码标记为不安全。
A little late but....
In order to use C# marshalling with arrays inside structs you have to declare them as "fixed", otherwise they are just pointers out to managed memory which will make a mess.
Its worth noting that "fixed" for some reason is an unsafe option and requires you flag your code as unsafe.
正如弗朗西在评论中所建议的那样,我能够使用这种方法让它工作(尽管我不确定这是否是他的意思)。
我不知道为什么另一种方法是提出 AV,我以前用过这种方法,没有任何问题。
I was able to get it to work using this method, as suggested by Franci in the comments (although I'm not sure if this is what he meant).
I do not know why the other way was raising an AV, I've used that method before with no issues.