2014-10-09 3 views
1

Я получил эту структуру:Marshal.PtrToStructure метания AccessViolationException

[StructLayout(LayoutKind.Sequential)] 
    public struct IS 
    { 
    public UInt32 ID; 
    public UInt32 Quality; 
    public UInt32 Flags; 
    public UInt32 Flags2;  
    public UInt32 ContainerSlots; 
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)] 
    public Int32[] ItemStatType; 
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)] 
    public UInt32[] ItemStatValue;  
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)] 
    public Int32[] ItemStatUnk1;  
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)] 
    public Int32[] ItemStatUnk2;  
    public UInt32 ScalingStatDistribution; 
    public UInt32 DamageType;  
    public UInt32 Delay;  
    public float RangedModRange; 
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 5)] 
    public Int32[] SpellId;   
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 5)] 
    public Int32[] SpellTrigger;  
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 5)] 
    public Int32[] SpellCharges; 
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 5)] 
    public Int32[] SpellCooldown; 
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 5)] 
    public Int32[] SpellCategory;  
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 5)] 
    public Int32[] SpellCategoryCooldown; 
    public UInt32 Bonding; 
    public string Name;  
    public string Name2;     
    public string Name3;   
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] 
    public UInt32[] Color; 
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] 
    public UInt32[] Content; 
}; 

И я пытаюсь прочитать байты из файла и скопировать эти байты в выше struct с помощью маршала и GCHandle, мой код следующим образом:

reader = BinaryReader.FromFile(fileName); 
m_rows = new List<IS>(); 
int size = Marshal.SizeOf(typeof(IS)); 
if(reader.BaseStream.Length < size) 
    return; 
byte[] buffer = new byte[size]; 
buffer = reader.ReadBytes(size); 
GCHandle handle = GCHandle.Alloc(buffer, GCHandleType.Pinned); 
m_rows.Add((IS)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(IS))); 
handle.Free(); 

Но я получаю AccessViolationException : attempt to read or write protected memory

Я понятия не имею, почему это исключение.

ответ

5

Я не сразу увидел ошибку и написал небольшую тестовую программу, чтобы воспроизвести проблему. Использование двоичного поиска, чтобы найти проблему, комментируя половину поля неоднократно, пока я не сузил его до:

[StructLayout(LayoutKind.Sequential)] 
public struct IS { 
    public string Name; 
} 

Это не может работать, то PInvoke маршаллер предполагает маршалинг по умолчанию для строки от строки C, char* , Это не может исправить данные, которые вы читаете из файла, он никогда не может содержать действительные указатели. AccessViolation запускается, когда он пытается разыменовать указатель.

В этом вопросе нет никаких намеков, чтобы угадать, как строка была фактически сериализована в файл. нормального путь:

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] 
public struct IS { 
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 42)] 
    public string Name; 
}; 

Используйте шестигранный зритель, если это необходимо, чтобы выяснить правильное значение SizeConst. Если кодировка необычна (а не системная страница по умолчанию), вы должны объявить ее как byte [] и использовать правильную кодировку для ее преобразования.

1

Нарушение прав доступа, как вы поняли из-за попытки прочитать нераспределенную память или память освобождения, вы можете проверить следующее переполнение стека проводки:

AccessViolationException when Marshal.PtrToStructure fires

Что относится к разнице между размер управляемой и собственной структуры в качестве причины проблемы, по сути, вам необходимо предоставить смещение во время сортировки, чтобы соответствовать разнице между управляемым и собственным распределением для структуры.

Проверить это размещение тоже, где смещение было добавлено пользователем

Access violation exception when use method Marshal.PtrToStructure in a loop.

Другим связующим звеном с раствором:

http://www.codeproject.com/Questions/585390/AccessplusViolationplusException

В случае, если это не помогает, то легко отлаживать такие вопросы с помощью WinDbg, я могу перечислить детали, в случае, если вам нужно сделать Это. Также включите исключение нарушения Win32 Aces в VS, оно сломается при исключении выделения строки с некоторой дополнительной информацией.

Смежные вопросы