0

我将保存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.

有谁知道出了什么问题?任何帮助将不胜感激。

4

1 回答 1

4

你为什么要传递fDeleteOld真实的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;
}

它之前崩溃的原因是因为传递fDeleteOldas true 假设您已经调用Marshal.StructureToPtr()了该 IntPtr。因为你没有,所以它崩溃了(内存块没有以 StructureToPtr() 期望的方式初始化)。

Marshal.DestroyStructure()但是,您仍然需要按照我上面的示例调用来清理内存。这是清理用于包含引用的结构的数据所必需的。(您的特定示例结构不包含引用,但您可以将这样的结构传递给您的StructureToByteArray())。

最后,请注意,如果您这样做,它不会崩溃(此代码除了演示如何使用fDeleteOld标志之外毫无意义):

Marshal.StructureToPtr(structure, ptr, false); // First time; must be false.
Marshal.StructureToPtr(structure, ptr, true); // Second time: Now it can be true.
于 2013-03-10T10:40:19.760 回答