Почему эта простая тривиальная программа настолько велика при компиляции?

Я создал файл, содержащий следующую строку:

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). так что отладчик может показать правильные ссылки на исходный код для выполнения.

Также: из-за того, как выкладывается память, двоичный файл обычно создается блоком фиксированного размера. Ваша программа может быть даже короче, но должен присутствовать хотя бы один сегмент кода, один инициализатор сегмента данных и один общий сегмент (для постоянных значений).