Почему эта простая тривиальная программа настолько велика при компиляции?
Я создал файл, содержащий следующую строку:
int main() { return 0; }
После компиляции, я был удивлен, узнав, что двоичный код для этой простой программы составляет 8328 байт! Что здесь происходит, и что в мире есть двоичный файл в этих 8328 байтах? Конечно, эта программа может быть выражена всего несколькими строками сборки.
Примечание. Я скомпилировал это со следующей строкой:
g++ main.cpp
Моя версия g++ g++ (Ubuntu/Linaro 4.6.1-9ubuntu3) 4.6.1
Ответы
Ответ 1
В этом двоичном файле много:
- заголовок, чтобы сделать двоичное самоописание (попробуйте запустить
file
на нем)
- таблица символов, которую инструмент
strip
удалит для вас (или ссылку с gcc -s
)
- имена и местоположения разделяемых библиотек, которые вы никогда не используете (пять из них на моем ящике, попробуйте инструменты
ldd
и strings
)
- который загружает эти библиотеки и устанавливает
argc
и argv
, затем вызывает main
- который возвращает
main
возвращаемое значение в операционную систему.
Для комического эффекта попробуйте связать эту программу статически, где ваш двоичный файл будет включать функции, которые обычно динамически связываются с DLL. (однако этот вариант упростит развертывание)
Ответ 2
Сделайте двоичный дамп результирующего файла и проверьте его!
В основном пустое пространство. Данные в двоичном формате организованы на страницы (обычно, 4096 или 8192 байта). Таким образом, страницы могут эффективно отображать карту памяти. Обычно первая страница содержит инструкции о том, как загрузить двоичный код, находится в этой позиции в файле и сопоставляется с этим местоположением, то же самое для данных и т.д. Вторая страница, вероятно, будет вашим кодом, а третья страница будет содержать символы и отладочную информацию. Каждая страница, вероятно, в основном пуста.
Ответ 3
Не беспокойтесь.
Попробуйте сделать менее тривиальную программу, и вы обнаружите, что размер не такой уж иный, пока ваш код не начнет составлять несколько сотен килобайт.
Вкратце:. В стандартной библиотеке есть "инфраструктура" между модулями ОС и семантикой С++, которые управляют запуском и завершением программы (все, что инициализирует и уничтожает глобальную переменные, стандартный ввод и вывод и т.д.)
Плюс: все, что сопоставляет символы С++ по адресам памяти (если вам не нужно было его удалять), попробуйте -O3
-s
и устраните опции -g
). так что отладчик может показать правильные ссылки на исходный код для выполнения.
Также: из-за того, как выкладывается память, двоичный файл обычно создается блоком фиксированного размера. Ваша программа может быть даже короче, но должен присутствовать хотя бы один сегмент кода, один инициализатор сегмента данных и один общий сегмент (для постоянных значений).