gpt4 book ai didi

c# - Marshal.PtrToStructure 抛出 AccessViolationException

转载 作者:行者123 更新时间:2023-11-30 19:16:13 29 4
gpt4 key购买 nike

我有这个结构:

    [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;
};

我正在尝试使用 Marshal 和 GCHandle 从文件中读取字节并将这些字节复制到上面的 struct 中,我的代码如下:

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

我不知道为什么会抛出这个异常。

最佳答案

我没有立即看到错误并编写了一个小测试程序来重现该问题。使用二进制搜索找到问题,重复注释掉一半的字段,直到我将范围缩小到:

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

那行不通,pinvoke 编码器假定 string 的默认编码来自 C 字符串 char*。这不可能更正您从文件中读取的数据,它永远不会包含有效的指针。 AccessViolation 在尝试取消引用指针时被触发。

问题中没有任何提示可以猜测字符串实际上是如何序列化到文件中的。 正常方式是:

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

如有必要,请使用十六进制查看器来确定 SizeConst 的正确值。如果编码不正常(不是系统默认页面),则必须将其声明为 byte[] 并使用适当的编码对其进行转换。

关于c# - Marshal.PtrToStructure 抛出 AccessViolationException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26276077/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com