Marshal.PtrToStructure中的访问冲突

时间:2009-09-09 17:49:35

标签: c# .net pinvoke

我正在尝试对结构进行反序列化,并且我在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;

}

最后一个参数(Option)是一个最大340字节(通常更短)的可变长度字段

1 个答案:

答案 0 :(得分:0)

我能够使用这种方法使用这种方法,正如Franci在评论中所建议的那样(虽然我不确定这是否是他的意思)。

我不知道为什么另一种方式是提高AV,我之前使用过这种方法没有问题。

    byte[] mem = new byte[sizeof(typeof(MyPacketDefinition))];
    Array.Copy(mem, receivedData, receivedData.Length);
    using (MemoryStream ms = new MemoryStream(mem))
    {
        using (BinaryReader br = new BinaryReader(ms))
        {
            byte[] buff = br.ReadBytes(Marshal.SizeOf(typeof(MyPacketDefinition )));

            GCHandle handle = GCHandle.Alloc(buff, GCHandleType.Pinned);
            try
            {
                MyPacketDefinition s = (MyPacketDefinition )Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(MyPacketDefinition ));
            }
            finally
            {
                handle.Free();
            }

        }
   }