Нарушение доступа в Marshal.PtrToStructure - PullRequest
1 голос
/ 09 сентября 2009

Я пытаюсь десериализовать структуру и получаю исключение AV в PtrToStructure. Единственный недостаток в том, что это структура переменной длины, поэтому мне нужно отрегулировать длину перед десериализацией. Вот мой код, есть что-то явно не так? Структура содержит только целочисленные / короткие / байтовые массивы, ничего особенного.

входящие данные имеют размер 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 голосов
/ 10 сентября 2009

Мне удалось заставить его работать, используя этот метод, как это было предложено Франци в комментариях (хотя я не уверен, что это он имел в виду).

Я не знаю, почему другим способом было поднять 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();
            }

        }
   }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...