Допустим, у вас есть структура в C ++ (с использованием MFC, скомпилированная 32-разрядная версия), которая определяется следующим образом:
#pragma pack (push, 1)
struct foo
{
float f;
int z;
DWORD k;
BYTE b;
int i;
};
#pragma pack (pop,1)
Теперь вы создаете файл с отображением в памяти, используя CreateFileMapping
в Windows, а затем вы записываете содержимое этой структуры в эту область памяти. Это глобально доступная карта памяти.
Теперь у вас есть приложение C # (скомпилированное 32-битное), и вы создаете структуру, подобную этой:
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct foo
{
double f;
int z;
int k;
byte b;
int i;
}
Теперь, когда C # читает данные, отображенные в памяти, они выглядят поврежденными. Если тип f
является double
как и выше, значения для этого конкретного члена являются ненужными, остальные члены имеют правильное содержимое. Если вы измените его на float
тогда все остальные участники тоже содержат мусор.
Мой вопрос, может ли быть так, что 1-байтовое выравнивание вызывает чтение мусора?
К сожалению, у меня нет кода, который читает / записывает карту памяти, но структура структуры такая же, как и выше.
Если выравнивание здесь не является проблемой, что может привести к тому, что оно станет ненужным? Попытка изменить типы различных членов вокруг несколько раз, без разницы.
Глядя на две структуры, они, очевидно, отличаются тем, что неуправляемый начинается с float
и управляемый начинается с double
, Очевидно, это означает, что структуры не совпадают. Управляемая структура на 4 байта длиннее, а все члены после первого смещены на 4 байта.
Теперь вы говорите, что когда у вас есть код в соответствии с вопросом, первое поле содержит мусор, но другие поля в порядке. Исходя из этого, единственный разумный вывод состоит в том, что сторона записи интерфейса выполняет запись по адресу, смещенному на 4 байта от того, который читает сторона чтения.
Выравнивание и упаковка не проблема здесь. Вы читаете с адреса 4 байта, отличного от того, который используется для выполнения записи.
Решение состоит в том, чтобы:
Это звучит как выравнивание, а не упаковка. C # обещает как минимум 4-байтовое выравнивание в 32-битном коде, чтобы обновление 32-битных примитивов было атомарным. Интересно, что будет, если вы поставите два поплавка вместо двойного для первого участника.