Проблема в том, как ваши данные представлены в памяти.
Предположим, у вас есть экземпляр структуры 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» в памяти для вашей переменной «number». (Обратите внимание, что эти байты расположены в обратном порядке, поскольку архитектура Intel — LittleEndian, подробности см. в разделе Endiannes.)
Тогда у нас есть следующие пять целых чисел: «00 00 00 00» = 0, «01 00 00 00» = 1, «02 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. Таким образом, содержимое памяти для переменной «number» = «05 00 00 00», что равно номеру пять. массив[0],массив1,массив[2],массив[3],массив[4 ] разложить по блокам памяти "00 00 00 00" = 0, "01 00 00 00" = 1, "02 00 00 00" = 2, "03 00 00 00" = 3, "04 00 00 00" = 4 Все остальное остается для переменной buffer[512]. Но в c++ sizeof(char) == 1. Тип данных char обычно используется для представления старого текста в стиле 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".
Это какие-то невалидные указатели, которые указывают черт знает куда. Вот почему вы получаете нарушение прав доступа, когда пытаетесь их разыменовать.
person
Anton Vorobyev
schedule
21.12.2015