Почему GCC не оптимизирует структуры?
Системы требуют, чтобы определенные примитивы были выровнены с определенными точками в памяти (от кратного числа байтов, кратного 4, коротких до байтов, кратных 2, и т. Д.). Конечно, они могут быть оптимизированы, чтобы тратить наименьшее количество места при заполнении.
Мой вопрос: почему GCC не делает это автоматически? Отсутствует ли более очевидная эвристика (переменные порядка от требования к наибольшему размеру до наименьшего)? Является ли некоторый код зависимым от физического упорядочения его структур (это хорошая идея)?
Я только спрашиваю, потому что GCC супер оптимизирован во многих отношениях, но не в этом, и я думаю, что должно быть какое-то относительно классное объяснение (к которому я не обращаю внимания).
7 ответов
gcc не переупорядочивает элементы структуры, потому что это нарушит стандарт Си. Раздел 6.7.2.1 стандарта C99 гласит:
Внутри объекта структуры члены, не являющиеся битовыми полями, и модули, в которых находятся битовые поля, имеют адреса, которые увеличиваются в порядке их объявления.
Структуры часто используются как представления порядка упаковки двоичных форматов файлов и сетевых протоколов. Это сломалось бы, если бы это было сделано. Кроме того, разные компиляторы будут оптимизировать вещи по-разному, и связать код вместе из обоих будет невозможно. Это просто невозможно.
GCC умнее большинства из нас в производстве машинного кода из нашего исходного кода; тем не менее, я дрожу, если это было умнее нас при перестройке наших структур, так как это данные, которые, например, могут быть записаны в файл. Структура, которая начинается с 4 символов и затем имеет 4-байтовое целое число, была бы бесполезна, если бы она читалась в другой системе, где GCC решила, что она должна переупорядочить элементы структуры.
У gcc SVN есть оптимизация реорганизации структуры (-fipa-struct-reorg), но она требует анализа всей программы и в настоящее время не очень эффективна.
Не говоря уже о том, что это хорошая идея, но вы, безусловно, можете написать код, который опирается на порядок членов структуры. Например, во время взлома люди часто приводят указатель на структуру как тип определенного поля внутри, к которому они хотят получить доступ, а затем используют арифметику указателя, чтобы туда попасть. Для меня это довольно опасная идея, но я видел, что она использовалась, особенно в C++, для того, чтобы заставить переменную, которая была объявлена закрытой, быть общедоступной, когда она находится в классе из сторонней библиотеки и публично не инкапсулирована. Изменение порядка членов полностью сломало бы это.
Компиляторы C автоматически не упаковывают структуры именно из- за проблем с выравниванием, о которых вы упоминали. Доступ не на границах слов (32-битный на большинстве процессоров) влечет за собой серьезные потери на x86 и приводит к фатальным ловушкам на архитектурах RISC.
Возможно, вы захотите попробовать последнюю версию gcc trunk или struct-reorg-branch, которая находится в стадии активной разработки.