[英]`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.