Вопросы по выравниванию памяти в структурах и переносимости оператора sizeof - PullRequest
0 голосов
/ 01 апреля 2012

У меня есть вопрос об заполнении структуры и оптимизации выравнивания памяти относительно структур на языке Си.Я отправляю структуру по сети, я знаю, что для целей оптимизации времени выполнения память внутри структуры не является смежной.Я провел несколько тестов на своем локальном компьютере, и действительно, sizeof (my_structure) отличался от суммы всех членов моей структуры.Я провел некоторое исследование, чтобы выяснить две вещи:

  • Сначала оператор sizeof () извлекает заполненный размер структуры (т. Е. Реальный размер, который будет храниться в памяти).

  • При указании атрибута __ __ (( __ упаковано __ )) в объявленииэтой структуры эта оптимизация отключена компилятором, поэтому sizeof (my_structure) будет точно таким же, как сумма полей моей структуры.

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

memcpy(struct_dest, struct_src, sizeof(struct_src)); 

Мне также интересно, какова реальная цель атрибута __ __ (( __ упаковано __ ))Используется ли для отправки менее важного количества данных по сети при отправке структурыre или он фактически используется, чтобы избежать какого-либо неопределенного и зависящего от платформы поведения оператора sizeof?

Заранее спасибо.

Ответы [ 3 ]

2 голосов
/ 01 апреля 2012

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

Однако вам также необходимо убедиться, что ваши типы данных имеют одинаковый размер, если вы используете этот подход.Например, в 64-битных системах long составляет 4 байта в Windows и 8 байтов почти везде.И вам также нужно решать проблемы с порядком байтов.Стандарт заключается в передаче по проводам в сетевом порядке байтов.На практике вам лучше использовать выделенную библиотеку сериализации, чем пытаться изобретать решения всех этих проблем.

2 голосов
/ 01 апреля 2012
Я отправляю структуру по сети

Стоп.Возможно, некоторые со мной не согласятся (на практике вы видите, что многие проекты делают это), но struct - это способ размещения вещей в памяти - это не механизм сериализации.Используя этот инструмент для работы, вы уже связываете себя с кучей непереносимых допущений.

Конечно, вы можете подделать его такими вещами, как прагмы и атрибуты дополнения структуры, но - можетевы действительно?Даже с этими непереносимыми механизмами вы никогда не знаете, какие причуды могут появиться.Я вспоминаю работу в кодовой базе, где использовались «упакованные» структуры, а затем внезапно перенес ее на платформу, где доступ должен был быть выровнен по словам ... даже если это был номинально тот же компилятор (таким образом, поддерживавший те же проприетарные расширения), которые он создавалдвоичные файлы, которые разбились.Любая боль, которую вы получаете по этому пути, вероятно, заслуживает, и я бы сказал, что принимайте ее, только если вы можете быть на 100% уверены, что она будет работать только в данном компиляторе и среде, и это никогда не изменится.Я бы сказал, что безопаснее всего написать правильный механизм сериализации, который не позволяет создавать структуры вокруг границ процесса.

1 голос
/ 01 апреля 2012

Всегда ли безопасно копировать структуру с помощью memcpy, например, используя оператор sizeof

Да, именно так и есть цель предоставления оператора sizeof.

Обычно __attribute__((__packed__)) используется не из соображений размера, но когда вы хотите убедиться, что расположение структуры точно такое, как вы хотите.

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

...