Мой объектный файл C++ слишком большой
Я работаю над программой на C++, и скомпилированный объектный код из одного файла из 1200 строк (который инициализирует довольно сложный конечный автомат) достигает почти мегабайта. Что может сделать файл таким большим? Есть ли способ найти то, что занимает место внутри объектного файла?
5 ответов
Может быть несколько причин, когда объектные файлы больше, чем они должны быть как минимум:
- статически включая зависимые библиотеки
- здание с отладочной информацией
- здание с профилирующей информацией
- создание (чрезвычайно) сложных структур данных с использованием шаблонов (возможно, рекурсивных буст-структур)
- не включать флаги оптимизации во время компиляции (экономит не так много и может вызвать трудности, если используется слишком сильно)
Сначала я предлагаю проверить, если вы строите с отладочной информацией, это вызывает наибольшее распространение в моем опыте.
(Я предполагаю, что у вас есть оптимизация и включено удаление мертвого кода).
Включите опцию "Создать файл карты" вашего компоновщика и проверьте вывод.
Распространенными виновниками являются макросы / шаблоны, которые генерируют большие объемы кода и большие глобальные объекты.
Возможно, некоторые шаблоны (особенно std::iostream
s) и, возможно, обширное встраивание (то есть классы, которые полностью определены в заголовке). Однако в чем проблема с 1-мегабайтным объектным файлом? Во время связывания это может привести к крошечному двоичному файлу. У меня есть проект с 20 МБ объектных файлов, который, например, связан в двоичный файл 700 КБ.
Обновление: может быть также некоторый большой статический массив / объект. Кроме того, с помощью MSVC++ и GCC вы можете посмотреть на сгенерированную сборку для файла, который может дать вам несколько советов (с GCC это g++ -S foo.cpp
, для MSVC++ это '/FA'). Либо вы увидите много экземпляров шаблонов, и в этом причина. Если нет, то это размер объекта static
объекты.
Вы можете, добавив флаги компиляции -flto -Wl,-allow-multiple-definition
и вы можете добавить -fuse-linker-plugin
. -Wa,-mbig-obj
не работают на архитектуре x86/32bit (только x64)
Другой возможной причиной является Link-Time Code Generation, опция VC++. Это перемещает серверную часть компилятора в компоновщик. Это обеспечивает лучшую оптимизацию, но теперь объектный файл должен содержать все внутренние структуры данных, обычно передаваемые между front- и backend.
Хорошей ставкой также было бы взглянуть на возможности, упомянутые в Инструменте, для анализа размера разделов ELF и символа, например:
nm -C --print-size --size-sort --radix=d tst.o
size -A -d tst.o | sort -k2 -n
Я видел случаи, когда символы отладки МАССИВНЫ в C++, например, в 30 раз больше, чем остальная часть двоичного файла, так что это определенно одна из вещей, на которую нужно обратить внимание, указанное вышеsize
команда сразу же подскажет вам из-за огромных разделов, связанных с отладкой, и вы можете дважды проверить, удалив двоичный файл с помощью strip
или g++ -s
.
Еще одна вещь, на которую следует обратить внимание, - это сэкономить ли место / время с помощью явного создания экземпляра шаблона: Явное создание экземпляра шаблона - когда оно используется? Раздел "Как быстро проанализировать вашу сборку, чтобы увидеть, много ли она выиграет от создания экземпляра шаблона" этого ответа также содержит методологию поиска повторяющихся объектов в объектных файлах в большом (C++) проекте.
Вот макрос, который я использую, чтобы увидеть значения времени компиляции:
template <size_t N> struct compile_time_number { private: typedef int check; };
#define compiler_check_number(N) ((compile_time_number< N >::check)0)
Тогда будьте счастливы во время компиляции, чтобы увидеть, какие символы занимают место.
Изменить: так как никто, кажется, не понимает этого, я поясню: способ использовать это, чтобы добавить compiler_check_number(sizeof(<insert struct or global variable here>))
, Компилятор выдаст размер переменной или структуры как ошибку времени компиляции. Очень редко код является причиной огромного объектного файла.
Я использую это все время, чтобы увидеть, насколько большие вещи без запуска отладчика.