簡體   English   中英

Marshal.PtrToStructure 中的訪問沖突

[英]Access Violation in 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;

}

最后一個參數 (Option) 是最大 340 字節(通常較短)的可變長度字段

正如Franci在評論中所建議的那樣,我能夠使用這種方法使其工作(盡管我不確定這是否就是他的意思)。

我不知道為什么以另一種方式提高視聽效果,我之前使用該方法沒有任何問題。

    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();
            }

        }
   }

有點晚了但是......

為了將 C# 編組與結構內的數組一起使用,您必須將它們聲明為“固定”,否則它們只是指向托管內存的指針,這會造成混亂。

值得注意的是,出於某種原因“固定”是一個不安全的選項,需要您將代碼標記為不安全。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM