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

前にクラッシュしていた理由は、fDeleteOldを true として渡すと、その IntPtrが既に呼び出されていると想定されるためです。Marshal.StructureToPtr()そうしなかったため、クラッシュしました (メモリ ブロックは 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 に答える