在显式结构上获得"错误对齐或非对象重叠"错误

mar*_*khc 4 .net c# marshalling

我正在尝试阅读/编辑暗黑破坏神的保存文件.这里的规格,如果有人感兴趣,但我不认为它与问题有关.

我有一个字节数组,其中包含我正在尝试解析某些结构的文件字节.我已经可以很好地读取文件头了,但是我遇到了任务数据问题.我得到了结构:

[StructLayout(LayoutKind.Explicit, Size = 10, Pack = 1)]
public struct QuestCompletationDataHeader {
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 4)]
    [FieldOffset(0)]
    public string Identifier;
    [FieldOffset(4)]
    uint _0x0004;
    [FieldOffset(8)]
    short _0x008;
}

[StructLayout(LayoutKind.Explicit, Size = 96, Pack = 1)]
public struct QuestData {
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 96, ArraySubType = UnmanagedType.U1)]
    [FieldOffset(0)]
    byte[] _0x0000; //Irrelevant for now.
}

[StructLayout(LayoutKind.Explicit, Size = 298, Pack = 1)]
public struct QuestCompletationData {
    [MarshalAs(UnmanagedType.LPStruct)]
    [FieldOffset(0)]
    QuestCompletationDataHeader Header;

    [MarshalAs(UnmanagedType.LPStruct)]
    [FieldOffset(10)]
    QuestData NormalQuests;

    [MarshalAs(UnmanagedType.LPStruct)]
    [FieldOffset(106)]
    QuestData NightmareQuests;

    [MarshalAs(UnmanagedType.LPStruct)]
    [FieldOffset(202)]
    QuestData HellQuests;

}
Run Code Online (Sandbox Code Playgroud)

D2SFile类:

[StructLayout(LayoutKind.Explicit, Size = 638, Pack = 1)]
public struct D2SFile {
    [MarshalAs(UnmanagedType.LPStruct)]
    [FieldOffset(0)]
    public D2SHeader Header;

    [MarshalAs(UnmanagedType.LPStruct)]
    [FieldOffset(335)]
    public QuestCompletationData Quests;
}
Run Code Online (Sandbox Code Playgroud)

并且函数Im用于执行字节到结构转换:

 public static D2SFile ByteArrayToD2SFile(byte[] bytes) {
        GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
        D2SFile stuff = (D2SFile)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(D2SFile));
        handle.Free();
        return stuff;
    }
Run Code Online (Sandbox Code Playgroud)

正如我所说,我已经可以单独读取文件头而没有问题,但是当我将任务数据添加到D2SFile结构时,我得到: Could not load type 'MedianXLEditor.QuestCompletationData' from assembly '...' because it contains an object field at offset 10 that is incorrectly aligned or overlapped by a non-object field.

mar*_*khc 5

由于没有人回答,我已经发现了什么是错的,我想我应该自己回答,以便任何碰巧在google搜索后结束的人都会有更轻松的时间.

事实证明,你不能有一个从不是4的倍数的偏移开始的数组.

在上面的示例中,QuestCompletationDataHeader长度为10个字节,因此在QuestCompletationData结构上,下一个字段将从位置10开始.下一个字段恰好是QuestData结构,它基本上是一个大数组(现在).因此它会尝试将该数组放在偏移量10,10处不是4的倍数,因此它给出了异常.

我更改了QuestData结构,因此它不在第一个位置使用数组,现在它工作正常.

此外,[MarshalAs(UnmanagedType.Struct)]当编组结构如上所述时使用.我正在使用[MarshalAs(UnmanagedType.LPStruct)],后来又给了我另一个例外.

  • 你到底是怎么想出来的? (2认同)