問題是您的數據在內存中的表現方式。
讓我們假設你有一個c#結構的實例,它封送到非託管代碼甚至是文件。
[StructLayout(LayoutKind.Sequential, Pack = 8)]
public struct Data
{
[MarshalAs(UnmanagedType.U4)]
public int number = 5;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 5)]
public int[] array = {0, 1, 2, 3, 4};
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 512)]
public string buffer = "Happy new Year";
}
根據這一點,你的內存佈局將是這樣的(十六進制樣視圖):
05 00 00 00 00 00 00 00
01 00 00 00 02 00 00 00
03 00 00 00 04 00 00 00
00 48 00 61 00 70 00 70
00 79 00 20 00 6E 00 65
00 77 00 20 00 59 00 65
00 61 00 72
在這裏,我們第一個四個字節「05 00 00 00」,這意味着數字「 5「在你的」數字「變量的內存中。 (請注意,以顛倒的次序這些字節因爲英特爾架構LittleEndian,見Endiannes瞭解詳細信息)
然後我們未來五年的整數爲 「00 00 00 00」= 0, 「01 00 00 00」= 1,「02對於名爲「array」的數組,「00 00 00」= 2,「03 00 00 00」= 3,「04 00 00 00」= 4。
和字符串「緩衝」表示這樣的:
"00 48" = H
"00 61" = a
"00 70" = p
"00 70" = p
"00 79" = y
"00 20" = <space>
"00 6E" = n
"00 65" = e
"00 77" = w
"00 20" = <space>
"00 59" = Y
"00 65" = e
"00 61" = a
"00 72" = r
有一些技巧的。NET始終使用Unicode來存儲它的字符串變量。每個Unicode字符都是雙字節表示。
現在,對於該C++結構
struct Data
{
public:
int number;
int array[5];
char buffer[512];
//char *buffer;
};
的sizeof(int)的是4。所以的記憶變量 「號碼」 的內容= 「05 00 00 00」,這是5號。在內存塊「00 00 00 00」= 0,「01 00 00 00」= 1,「02 00 00 00」上佈置陣列[0],陣列1,陣列[2],陣列[3],陣列[4] 「= 2,」03 00 00 00「= 3,」04 00 00 00「= 4. 其他所有內容都保留在緩衝區[512]變量中。但在C++中,sizeof(char)== 1。字符數據類型通常用於用單字節編碼表示舊的ASCII樣式文本。您應該使用wchar_t來代替它,它非常適合Unicode編碼。
現在讓我們來看看
struct Data
{
public:
int number;
int *array;
char *buffer;
};
這種結構將在相同的內存佈局上述的投影。 如果您在32位環境(win32) 下運行,則「數組」指針的內容將爲「00 00 00 00」(4字節用於指針) 並且「緩衝區」指針將爲「01 00 00 00」 。
如果您在64位環境(win64) 下運行,「數組」指針的內容將爲「00 00 00 00 01 00 00 00」(指針爲8個字節),緩衝區指針爲「02 00 00 00 03 00 00 00「。
這些是一些指向誰知道在哪裏的無效指針。這就是爲什麼當你試圖解引用它們時你會得到訪問衝突。
如果不更改C#聲明,則無法更改C++聲明。之後你很快會發現int []不會飛。帶指針的結構是一個非常討厭的內存管理問題,但是誰又不能再次釋放內存是非常明確的。你必須自己承擔責任並使用IntPtr。並擔心C++代碼是否要深拷貝數組和字符串,如果沒有,那麼你有下一個問題保持這些指針有效。 –