то, почему мой C++ произвел исполняемый файл, является настолько большим?

У меня есть довольно простой проект C++, который использует повышение:: библиотека regex. Вывод, который я получаю, составляет 3.5 МБ в размере. Поскольку я понимаю, что статически связываю все повышение.CPP файлы, включая все функции/методы. Возможно, возможно так или иначе дать моему компоновщику команду использовать только необходимые элементы от повышения, не всех их?Спасибо.

$ c++ —version
i686-apple-darwin10-g++-4.2.1 (GCC) 4.2.1 (Apple Inc. build 5659)

Это что size говорит:

$ size a.out
__TEXT  __DATA  __OBJC  others  dec hex
1556480 69632   0   4296504912  4298131024  100304650

Я попробовал strip:

$ ls -al
...  3946688 May 21 13:20 a.out
$ strip a.out
$ ls -al
...  3847248 May 21 13:20 a.out

PS. Это - то, как мой код организован (возможно, это - основная причина проблемы):

// file MyClass.h
class MyClass {
  void f();
};
#include "MyClassImpl.h"

// file MyClassImpl.h
void MyClass::f() {
  // implementation...
}

// file main.cpp
#include "MyClass.h"
int main(int ac, char** av) {
  MyClass c;
  c.f();
}

Что Вы думаете?

14
задан yegor256 25 May 2010 в 11:00
поделиться

6 ответов

Вы компилировали с включенными отладочными символами? Это могло объяснить большую часть размера. Также как вы определяете размер двоичного файла? Предполагая, что вы работаете на платформе, подобной UNIX, используете ли вы прямую команду « ls -l » или « size ». Эти два могут дать очень разные результаты, если двоичный файл содержит символы отладки. Например, вот результаты, которые я получаю при создании примера Boost.Regex " credit_card_example.cpp ".

$ g++ -g -O3 foo.cpp -lboost_regex-mt

$ ls -l a.out 
-rwxr-xr-x 1 void void 483801 2010-05-20 10:36 a.out

$ size a.out
   text    data     bss     dec     hex filename
  73330     492     336   74158   121ae a.out

Аналогичные результаты возникают при простом создании объектного файла:

$ g++ -c -g -O3 foo.cpp

$ ls -l foo.o 
-rw-r--r-- 1 void void 622476 2010-05-20 10:40 foo.o

$ size foo.o
   text    data     bss     dec     hex filename
  49119       4      40   49163    c00b foo.o

РЕДАКТИРОВАТЬ : добавлены некоторые результаты статической компоновки ...

Вот двоичный размер при статической компоновке. Это ближе к тому, что вы получаете:

$ g++ -static -g -O3 foo.cpp -lboost_regex-mt -lpthread

$ ls -l a.out 
-rwxr-xr-x 1 void void 2019905 2010-05-20 11:16 a.out

$ size a.out 
   text    data     bss     dec     hex filename
1204517    5184   41976 1251677  13195d a.out

Также возможно, что большая часть большого размера поступает из других библиотек, от которых зависит библиотека Boost.Regex. На моем компьютере с Ubuntu зависимости для разделяемой библиотеки Boost.Regex следующие:

$ ldd /usr/lib/libboost_regex-mt.so.1.38.0 
        linux-gate.so.1 =>  (0x0053f000)
        libicudata.so.40 => /usr/lib/libicudata.so.40 (0xb6a38000)
        libicui18n.so.40 => /usr/lib/libicui18n.so.40 (0x009e0000)
        libicuuc.so.40 => /usr/lib/libicuuc.so.40 (0x00672000)
        librt.so.1 => /lib/tls/i686/cmov/librt.so.1 (0x001e2000)
        libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0x001eb000)
        libm.so.6 => /lib/tls/i686/cmov/libm.so.6 (0x00110000)
        libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x009be000)
        libpthread.so.0 => /lib/tls/i686/cmov/libpthread.so.0 (0x00153000)
        libc.so.6 => /lib/tls/i686/cmov/libc.so.6 (0x002dd000)
        /lib/ld-linux.so.2 (0x00e56000)

Библиотеки ICU могут стать довольно большими. Помимо отладочных символов, возможно, именно они вносят основной вклад в размер вашего двоичного файла. Более того, в случае со статической связью кажется, что сама библиотека Boost.Regex состоит из больших объектных файлов:

$ size --totals /usr/lib/libboost_regex-mt.a | sort -n
      0       0       0       0       0 regex_debug.o (ex /usr/lib/libboost_regex-mt.a)
      0       0       0       0       0 usinstances.o (ex /usr/lib/libboost_regex-mt.a)
      0       0       0       0       0 w32_regex_traits.o (ex /usr/lib/libboost_regex-mt.a)
   text    data     bss     dec     hex filename
    435       0       0     435     1b3 regex_raw_buffer.o (ex /usr/lib/libboost_regex-mt.a)
    480       0       0     480     1e0 static_mutex.o (ex /usr/lib/libboost_regex-mt.a)
   1543       0      36    1579     62b cpp_regex_traits.o (ex /usr/lib/libboost_regex-mt.a)
   3171     632       0    3803     edb regex_traits_defaults.o (ex /usr/lib/libboost_regex-mt.a)
   5339       8      13    5360    14f0 c_regex_traits.o (ex /usr/lib/libboost_regex-mt.a)
   5650       8      16    5674    162a wc_regex_traits.o (ex /usr/lib/libboost_regex-mt.a)
   9075       4      32    9111    2397 regex.o (ex /usr/lib/libboost_regex-mt.a)
  17052       8       4   17064    42a8 fileiter.o (ex /usr/lib/libboost_regex-mt.a)
  61265       0       0   61265    ef51 wide_posix_api.o (ex /usr/lib/libboost_regex-mt.a)
  61787       0       0   61787    f15b posix_api.o (ex /usr/lib/libboost_regex-mt.a)
  80811       8       0   80819   13bb3 icu.o (ex /usr/lib/libboost_regex-mt.a)
 116489       8     112  116609   1c781 instances.o (ex /usr/lib/libboost_regex-mt.a)
 117874       8     112  117994   1ccea winstances.o (ex /usr/lib/libboost_regex-mt.a)
 131104       0       0  131104   20020 cregex.o (ex /usr/lib/libboost_regex-mt.a)
 612075     684     325  613084   95adc (TOTALS)

Вы можете получить до ~ 600 КБ, поступающих только от Boost.Regex, если некоторые или все эти объектные файлы будут связаны в ваш двоичный файл.

17
ответ дан 1 December 2019 в 10:02
поделиться

Если вы статически связываете, то большинство компоновщиков будет включать только те объекты, которые необходимы.

3,5 МБ - это не так уж и много - в системе ПК, поэтому размер может зависеть от ОС и т. Д.

2
ответ дан 1 December 2019 в 10:02
поделиться

Флаг -O3 оптимизирует код не по размеру, а по скорости выполнения. Так что, возможно, например, некоторое разгрузка цикла приведет к большему размеру файла. Попробуйте скомпилировать с каким-нибудь другим флагом оптимизации. Флаг -Os будет оптимизирован для небольшого исполняемого файла.

6
ответ дан 1 December 2019 в 10:02
поделиться

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

Более вероятно, что отладочная информация / таблица символов и т. Д. Занимает место в вашем двоичном файле. Имена шаблонов (например, iostream и стандартные контейнеры) очень длинные и создают большие записи в таблице символов.

Вы не говорите, какую ОС вы используете, но если это вариант unix в качестве теста, вы можете фактически удалить копию вашего двоичного файла, чтобы удалить всю лишнюю информацию и посмотреть, что осталось:

cp a.out a.out.test
strip a.out.test
ls -l a.out*

На одном двоичном файле, который я тестировал, он удалил около 90% размера файла. Обратите внимание, что если вы сделаете это, любые ядра будут бесполезны без копии нераспакованного двоичного файла для отладки - у вас не будет никаких имен символов или чего-либо еще, только сборка и адреса. 3,5 МБ - это действительно крошечный файл в наше время. Скорее всего, там просто столько отладочной / символьной информации даже из 10 КБ источника.

1
ответ дан 1 December 2019 в 10:02
поделиться

Вы говорите, что у вас 3 файла. Для меня MyClassImpl.h, вероятно, является .cpp, поскольку он содержит реализацию.

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

Это связано с тем, что большинство функций повышения - это встроенные шаблоны.

лучший,

1
ответ дан 1 December 2019 в 10:02
поделиться

, если у вас есть ldd, вы можете использовать его, чтобы проверить, действительно ли вы связываетесь со всеми библиотеками boost.

Другая возможность состоит в том, что размер является побочным эффектом использования библиотек только для заголовков, многие библиотеки Boost имеют такой тип, и включение их может встраивать больше кода, чем вы могли бы поверить. Вы также можете создать своего рода комбинаторный взрыв из-за использования нескольких различных параметров шаблона.

Чтобы получить лучшую диагностику, вы должны попытаться создать действительно короткую программу с использованием регулярного выражения и посмотреть, какой размер вы получите. Если ваша программа действительно короткая, то 3,5 Месяца - это довольно много. Мой текущий исполняемый файл projet также использует BOOST (но не регулярное выражение) и имеет примерно такой же размер. Но я говорю примерно о 20000 строках C ++. Следовательно, где-то должна быть загвоздка.

0
ответ дан 1 December 2019 в 10:02
поделиться
Другие вопросы по тегам:

Похожие вопросы: