簡體   English   中英

Marshal.StructureToPtr引發異常,試圖獲取結構的字節數組表示形式

[英]`Marshal.StructureToPtr` throws exception trying to get byte array representation of a structure

我將把DataTable保存到* .dbf文件(dBase IV)。 所以我有一個這樣的結構:

[StructLayout(LayoutKind.Explicit, Pack = 1)]
public struct DbfHeader
{
    [FieldOffset(0)]
    private byte versionNumber;

    [FieldOffset(1)]
    private byte yearOfLastUpdate;

    [FieldOffset(2)]
    private byte monthOfLastUpdate;

    [FieldOffset(3)]
    private byte dayOfLastUpdate;

    [FieldOffset(4)]
    private Int32 numberOfRecords;

    [FieldOffset(8)]
    private Int16 lengthOfHeader;

    [FieldOffset(10)]
    private Int16 lengthOfEachRecord;

    [FieldOffset(12)]
    private Int16 reserved1;

    [FieldOffset(14)]
    private byte incompleteTransaction;

    [FieldOffset(15)]
    private byte encryptionFlag;

    [FieldOffset(16)]
    private byte[] freeRecordThread;

    [FieldOffset(20)]
    private byte[] reserved2;

    [FieldOffset(28)]
    private byte mdxFlag;

    [FieldOffset(29)]
    private byte languageDriver;

    [FieldOffset(30)]
    private Int16 reserved3;

    public DbfHeader(int numberOfRecords, int numberOfFields, short recordLength, Encoding encoding)
    {
        // some code that initialize each field
    }

}

另外,我有一個將DbfHeader變量轉換為byte[]數組的方法,如下所示:

public static byte[] StructureToByteArray<T>(T structure)
{
    int len = Marshal.SizeOf(structure);
    byte[] result = new byte[len];
    IntPtr ptr = Marshal.AllocHGlobal(len);
    Marshal.StructureToPtr(structure, ptr, true);
    Marshal.Copy(ptr, result, 0, len);
    Marshal.FreeHGlobal(ptr);
    return result;
}

但是這種方法不起作用。 Marshal.StructureToPtr(structure, ptr, true)行中,出現以下異常:

Attempted to read or write protected memory. 
This is often an indication that other memory is corrupt.

有人知道怎么了嗎? 任何幫助將不勝感激。

為什么將fDeleteOld作為true傳遞給Marshal.StructureToPtr()

據我所知,您應該傳遞false

我認為您也應該在復制內存后調用Marshal.DestroyStructure():

public static byte[] StructureToByteArray<T>(T structure)
{
    int len = Marshal.SizeOf(structure);
    byte[] result = new byte[len];
    IntPtr ptr = Marshal.AllocHGlobal(len);
    Marshal.StructureToPtr(structure, ptr, false);
    Marshal.Copy(ptr, result, 0, len);
    Marshal.DestroyStructure(ptr, typeof(T));
    Marshal.FreeHGlobal(ptr);
    return result;
}

它之前崩潰的原因是因為將fDeleteOld傳遞為true假設您已經為該IntPtr調用了Marshal.StructureToPtr() 因為您沒有這樣做,它崩潰了(內存塊未按照StructureToPtr()的預期方式進行初始化)。

但是,按照上面的示例,您仍然需要通過調用Marshal.DestroyStructure()來清理內存。 這是清理包含引用的結構所使用的數據所必需的。 (您的特定示例struct不包含引用,但是您可以將這樣的結構傳遞給StructureToByteArray() )。

最后,請注意,如果執行此操作,則不會崩潰(此代碼fDeleteOld除了演示如何使用fDeleteOld標志):

Marshal.StructureToPtr(structure, ptr, false); // First time; must be false.
Marshal.StructureToPtr(structure, ptr, true); // Second time: Now it can be true.

暫無
暫無

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

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