Можно ли разделить структуру C в разделяемой памяти между приложениями, скомпилированными с разными компиляторами? - PullRequest
2 голосов
/ 20 января 2010

Я понимаю, что в целом стандарты C и C ++ дают авторам компиляторов большую свободу действий. Но, в частности, это гарантирует, что типы POD, такие как члены структуры C, должны быть размещены в памяти в том же порядке, в котором они перечислены в определении структур, и большинство компиляторов предоставляют расширения, позволяющие исправить выравнивание элементов. Поэтому, если у вас был заголовок, который определил структуру и вручную указал выравнивание ее членов, а затем скомпилировал два приложения с разными компиляторами, используя заголовок, не должно ли одно приложение записать экземпляр структуры в общую память, а другое - приложение сможет прочитать его без ошибок?

Я предполагаю, однако, что размер содержащихся типов одинаков для двух компиляторов на одной архитектуре (это должна быть уже одна и та же платформа, поскольку мы говорим об общей памяти). Я понимаю, что это не всегда верно для некоторых типов (например, long и long в 64-битных GCC и MSVC), но в настоящее время существуют типы uint16_t, uint32_t и т. Д., А типы float и double определяются стандартами IEEE.

Ответы [ 5 ]

2 голосов
/ 20 января 2010

Пока вы можете гарантировать одинаковую структуру памяти, включая смещения, а типы данных имеют одинаковый размер для двух компиляторов, тогда да, это нормально. Потому что в этот момент структура идентична в отношении доступа к данным.

1 голос
/ 20 января 2010

Да, конечно. Я делал это много раз. Проблемы и решения одинаковы, независимо от того, скомпилирован ли и смешан ли смешанный код, или при передаче данных в формате struct между машинами.

В старые добрые времена это часто происходило при интеграции MS C и почти всего остального: Borland Turbo C. DEC VAX C, Greenhills C.

Самая простая часть - получить количество байтов для различных типов данных для согласования. Например, short на 32-разрядном компиляторе с одной стороны совпадает с int на 16-разрядном компиляторе на другом конце. Поскольку общий исходный код для объявления структур, как правило, полезен, полезно использовать несколько объявлений типа «точка»:

typedef  signed long     s32;
typedef  signed short    s16;
typedef  signed char     s8;
typedef  unsigned long   u32;
typedef  unsigned short  u16;
typedef  unsigned char   u8;
...

Microsoft C самая раздражающая. По умолчанию он дополняет элементы до 16-битного выравнивания, а может и больше с 64-битным кодом. Другие компиляторы на x86 не дополняют членов.

struct {
    int   count;
    char  type;
    char  code;
    char  data [100];
} variable;

Может показаться, что смещение code должно быть следующим байтом после type, но между ними может быть вставлен дополняющий байт. Исправление обычно

#ifdef _MSC_VER    // if it's any Microsoft compiler
 #pragma pack(1)   // byte align structure members--that is, no padding
#endif

Существует также опция командной строки компилятора, чтобы сделать то же самое.

0 голосов
/ 15 апреля 2010

См. Руководства к вашему компилятору.

большинство компиляторов предоставляют расширения, позволяющие фиксировать выравнивание элементов

Вы ограничиваете себя этими компиляторами и взаимно совместимым стилем #pragma align? Если это так, то безопасность определяется их спецификацией.

В интересах переносимости вам, вероятно, лучше отказаться от #pragma align и полагаться на свой ABI, который может обеспечить «разумный» стандарт для соответствия всех компиляторов вашей платформы.

Поскольку стандарты C и C ++ допускают любую детерминистическую методологию структурирования структуры, они по существу не имеют значения.

0 голосов
/ 20 января 2010

Это действительно возможно, вам просто нужно убедиться, что все задействованные компиляторы генерируют одинаковую структуру данных из одного и того же кода. Один из способов проверить это - написать пример программы, которая создает структуру и записывает ее в двоичный файл. Откройте полученные файлы в шестнадцатеричном редакторе и убедитесь, что они совпадают. Кроме того, вы можете привести структуру к массиву uint8_t и вывести отдельные байты на экран.

Один из способов убедиться, что размеры данных одинаковы, - это использовать типы данных, такие как int16_t (из stdint.h) вместо простого старого int, который может изменять размеры между компиляторами (хотя это редко два компилятора, работающие на одной платформе).

Это не так сложно, как кажется. Существует множество предварительно скомпилированных библиотек, которые можно использовать с несколькими компиляторами. Главное - создать тестовую программу, которая позволит вам убедиться, что оба компилятора одинаково относятся к структуре.

0 голосов
/ 20 января 2010

Способ размещения памяти важен в дополнение к размеру типа данных, если вам нужна структура из библиотеки 1, скомпилированная компилятором 1, для использования в библиотеке 2, скомпилированной компилятором 2.

...