GCC C ++ & ldquo; Hello World & rdquo; программа - > Размер файла .exe составляет 500 КБ при компиляции в Windows. Как я могу уменьшить его размер?

setTimeout('$("#someDivId").hide()',1500);
29
задан zeroDivisible 25 June 2009 в 11:17
поделиться

13 ответов

#include <iostream>

вызывает связывание многих стандартных библиотек, по крайней мере, с g ++. Если вы действительно обеспокоены размером исполняемого файла, попробуйте заменить все случаи использования iostreams на printf или аналогичные. Это, как правило, дает вам меньший, более быстрый исполняемый файл (я получил ваш около 6K) за счет удобства и безопасности типов.

21
ответ дан 25 June 2009 в 11:17
поделиться

Большая часть размера связана с использованием довольно обширных библиотек времени выполнения. Так что в реальной жизни вы на самом деле связываете очень большой кусок «мертвого кода», если у вас есть такое простое приложение.

Насколько я знаю, нет никаких флагов компоновщика, чтобы пропустить неиспользуемые части связанной библиотеки.

Есть два способа подделки меньшего приложения:

  1. Использовать динамическое связывание. Тогда ваше приложение ссылается на динамически загружаемую библиотеку. Вам по-прежнему нужен полный размер (на самом деле больше), но у вас гораздо меньший исполняемый файл.
  2. Используйте исполняемую систему сжатия .
0
ответ дан Niels Basjes 25 June 2009 в 11:17
поделиться

Если вам нужны небольшие исполняемые файлы, Tiny C скомпилирует исполняемый файл размером 1536 байт для printf («Привет, мир!»). TinyC - это всего лишь C, а не C ++, и известно, что он компилируется быстрее и дает более медленные исполняемые файлы, чем gcc.

РЕДАКТИРОВАНИЕ: Я только что попробовал cout < "Hello World!" в DevC ++ (связывает Mingw 4.8 и Ide), и я получил исполняемый файл размером 4,5 МБ !!

2
ответ дан Antoni Gual Via 25 June 2009 в 11:17
поделиться

Я повторил ваш тест, используя Cygwin и g ++. Ваш код скомпилирован в 480k с -O2. Запуск полосы на исполняемом файле уменьшил его до 280k.

В целом, я подозреваю, что ваша проблема заключается в использовании заголовка < iostream>. Это приводит к подключению довольно большой библиотеки. Также обратите внимание, что cout << x делает гораздо больше, чем просто печатает. Здесь есть локали, ручьи и всякие вещи под капотом.

Если, однако, иметь маленький исполняемый размер - это реальная, критически важная задача, то избегайте ее и используйте printf или put. Если это не так, то я бы сказал, заплатите единовременную стоимость iostream и покончите с этим.

2
ответ дан Kaz Dragon 25 June 2009 в 11:17
поделиться

Как другие компиляторы, такие как msvc8 или даже компилятор порядка, такие как borland c ++ 5.5.1, способны создавать очень маленькие исполняемые файлы, а mingw gcc не может?

Я сделал быструю компиляцию «Привет мир» для каждого из следующих наборов инструментов и наблюдал размер скомпилированного исполняемого файла. Обратите внимание, что во всех этих случаях библиотека времени выполнения статически связана, и все символы отладки удалены:

compiler toolchain            exe size                   exe size
                              (w/iostream header)        (w/cstdio printf)
-------------------------------------------------------------------------
Borland C++ 5.5.1             110kbyte                    52kbyte
MSVC 2008 express             102kbyte                    55kbyte
MinGW- GCC 3.4.5              277kbyte                    <10kbyte
MinGW- GCC 4.4.1              468kbyte                    <10kbyte

Что интересно, более поздняя версия gcc 4.4.1 производит даже больший исполняемый файл, чем gcc3.4.5 , вероятно, из-за другой версии libstdc ++.

Так есть ли способ удалить мертвый код на этапе компоновки для mingw?

1
ответ дан greatwolf 25 June 2009 в 11:17
поделиться

Если вы используете утилиту «nm» или какую-либо другую программу, которая показывает, что находится в вашем .exe, вы увидите, что она содержит тонны классов, которые кто-то может захочет использовать, но вы не наденете «т.

2
ответ дан Mike Dunlavey 25 June 2009 в 11:17
поделиться

Вы всегда можете запустить UPX на вашем exe после того, как вы его создали.

2
ответ дан SteveL 25 June 2009 в 11:17
поделиться

Вы получаете стандартную библиотеку C ++ и другие вещи, которые, я думаю, статически связаны, поскольку у mingw есть собственная реализация этих библиотек.

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

8
ответ дан nos 25 June 2009 в 11:17
поделиться

По сути, вы ничего не можете сделать, чтобы уменьшить размер .exe с помощью базового дистрибутива mingw. 550kb - это как можно меньше, потому что mingw и gcc / g ++ в целом плохо разбирают неиспользуемые функции. Около 530 КБ этого из библиотеки msvcrt.a.

Если вы действительно хотите в нее войти, вы можете перестроить библиотеку msvcrt.a с опциями компилятора -ffunction-section -fdata-section, а затем использовать -Wl, - gc-section опции компоновщика при связывании вашего приложения, и это должно быть в состоянии убрать много всего этого оттуда. Но если вы только изучаете C ++, перестройка этой библиотеки может быть немного продвинутой.

Или вы можете просто использовать MSVC, который отлично удаляет неиспользуемые функции. Тот же самый фрагмент кода, скомпилированный с MSVC, создает исполняемый файл размером 10 КБ.

4
ответ дан Gerald 25 June 2009 в 11:17
поделиться

Вы можете использовать -s, который, я считаю, также встроен в mingw. Простое приложение hello world, скомпилированное с использованием g ++ 3.4.4 на cygwin, произвело исполняемый файл размером 476872 байта, снова скомпилированный с -s (удаляет ненужные данные), уменьшив тот же исполняемый файл до 276480 байтов.

То же самое приложение hello world на cygwin, использующее g ++ 4.3.2, произвело исполняемый файл размером 16495 байт, а использование strip уменьшило размер до 4608 байт. Насколько я вижу, вероятно, лучше использовать более свежую версию g ++.

MingW только что выпустил gcc 4.4.0, поэтому, если важен размер исполняемого файла, я бы подумал об этом. Как он указывает, -s, вероятно, поможет убрать большую часть отладочной информации для вас, что рекомендуется только в том случае, если оно предназначено для производственного использования.

9
ответ дан Randai 25 June 2009 в 11:17
поделиться

Не уверен, насколько это будет полезно для вас, но кто-то проделал довольно большую работу по уменьшению размера простого Windows .exe .

Они смогли создать простой .exe-файл, который будет выполняться в современной версии Windows размером 133 байта, используя некоторые очень экстремальные методы.

10
ответ дан Salman Abbas 25 June 2009 в 11:17
поделиться

Что ж, когда вы используете стандартную библиотеку C ++, exe может стать очень быстрой. Если после удаления символа отладки вы все еще хотите уменьшить размер своего программного обеспечения, вы можете использовать упаковщик, такой как UPX . Но, будьте осторожны, некоторые антивирусы задыхаются от exe-файла, упакованного с UPX, так как некоторые вирусы использовали его давно.

2
ответ дан Raoul Supercopter 25 June 2009 в 11:17
поделиться

Проблема здесь не столько в библиотеке, сколько в том, как библиотека
связана. Конечно, iostream - библиотека среднего размера, но я не
думаю, что она может быть настолько огромной, чтобы заставить программу сгенерировать исполняемый файл
900KB больше, чем аналогичный, использующий C функции. Виноват
не iostream, а gcc. Точнее, виноват static linking.

Как бы вы объяснили эти результаты (с помощью вашей программы):

g++ test.cpp -o test.exe              SIZE: 935KB
gcc test.cpp -o test.exe -lstdc++     SIZE: 64.3KB

Различные размеры исполняемых файлов генерируются с одинаковыми параметрами сборки
.

Ответ заключается в том, как gcc связывает объектные файлы.
Когда вы сравните выходные данные этих двух команд:

g++ -v test.cpp -o test.exe // c++ program using stream functions  
gcc -v test.c -o test.exe   // c program that using printf  

вы обнаружите, что единственные места, где они отличаются (кроме путей к временным объектным файлам
), находятся в Используемые опции:

   C++(iostream) | C(stdio)
-------------------------------
-Bstatic         |  (Not There)
-lstdc++         |  (Not There)
-Bdynamic        |  (Not There)
-lmingw32        | -lmingw32 
-lgcc            | -lgcc 
-lmoldname       | -lmoldname 
-lmingwex        | -lmingwex 
-lmsvcrt         | -lmsvcrt 
-ladvapi32       | -ladvapi32 
-lshell32        | -lshell32 
-luser32         | -luser32 
-lkernel32       | -lkernel32 
-lmingw32        | -lmingw32 
-lgcc            | -lgcc 
-lmoldname       | -lmoldname 
-lmingwex        | -lmingwex 
-lmsvcrt         | -lmsvcrt 

У вас есть преступник прямо наверху. -Bstatic - это опция, которая появляется
точно после объектного файла, который может выглядеть примерно так:

"AppData\\Local\\Temp\\ccMUlPac.o" -Bstatic -lstdc++ -Bdynamic ....

Если вы поэкспериментируете с опциями и удалите «ненужные» библиотеки,
вы можете уменьшить размер исполняемого файла с 934KB до 4.5KB max
в моем случае. Я получил это 4.5KB, используя -Bdynamic, флаг -O
и самые важные библиотеки, без которых ваше приложение не может жить, то есть
-lmingw32, -lmsvcrt, -lkernel32. Вы получите 25KB исполняемый файл в этой точке
. Разденьте его до 10KB и UPX до около 4.5KB-5.5KB.

Вот Makefile для игры, для ударов:

## This makefile contains all the options GCC passes to the linker
## when you compile like this: gcc test.cpp -o test.exe
CC=gcc

## NOTE: You can only use OPTIMAL_FLAGS with the -Bdynamic option. You'll get a
## screenfull of errors if you try something like this: make smallest type=static
OPTIMAL_FLAGS=-lmingw32 -lmsvcrt -lkernel32

DEFAULT_FLAGS=$(OPTIMAL_FLAGS) \
-lmingw32 \
-lgcc \
-lmoldname \
-lmingwex \
-lmsvcrt \
-ladvapi32 \
-lshell32 \
-luser32 \
-lkernel32 \
-lmingw32 \
-lgcc  \
-lmoldname \
-lmingwex \
-lmsvcrt


LIBRARY_PATH=\
-LC:\MinGW32\lib\gcc\mingw32\4.7.1 \
-LC:\mingw32\lib\gcc \
-LC:\mingw32\lib\mingw32\lib \
-LC:\mingw32\lib\

OBJECT_FILES=\
C:\MinGW32\lib\crt2.o \
C:\MinGW32\lib\gcc\mingw32\4.7.1\crtbegin.o

COLLECT2=C:\MinGW32\libexec\gcc\mingw32\4.7.1\collect2.exe

normal:
    $(CC) -c test.cpp
    $(COLLECT2) -Bdynamic $(OBJECT_FILES)  test.o -B$(type) -lstdc++ -Bdynamic  $(DEFAULT_FLAGS) $(LIBRARY_PATH) -o test.exe

optimized:
    $(CC) -c -O test.cpp
    $(COLLECT2) -Bdynamic $(OBJECT_FILES)  test.o -B$(type) -lstdc++ -Bdynamic  $(DEFAULT_FLAGS) $(LIBRARY_PATH) -o test.exe

smallest:
    $(CC) -c -O test.cpp
    $(COLLECT2) -Bdynamic $(OBJECT_FILES)  test.o -B$(type) -lstdc++ -Bdynamic  $(OPTIMAL_FLAGS) $(LIBRARY_PATH) -o test.exe

ultimate:
    $(CC) -c -O test.cpp
    $(COLLECT2) -Bdynamic $(OBJECT_FILES)  test.o -B$(type) -lstdc++ -Bdynamic  $(OPTIMAL_FLAGS) $(LIBRARY_PATH) -o test.exe
    strip test.exe
    upx test.exe

CLEAN:
    del *.exe *.o

Результаты (YMMV):

// Not stripped or compressed in any way
make normal    type=static     SIZE: 934KB
make normal    type=dynamic    SIZE: 64.0KB

make optimized type=dynamic    SIZE: 30.5KB
make optimized type=static     SIZE: 934KB

make smallest  type=static     (Linker Errors due to left out libraries)
make smallest  type=dynamic    SIZE: 25.6KB 

// Stripped and UPXed
make ultimate type=dynamic    (UPXed from 9728 bytes to 5120 bytes - 52.63%)
make ultimate type=static     (Linker Errors due to left out libraries)

Возможная причина включения -Bstatic в параметры сборки по умолчанию
предназначены для лучшей производительности. Я попытался собрать astyle с -Bdynamic и получил
снижение скорости в среднем на 1 секунду, хотя приложение было на
меньше, чем оригинал (400 КБ против 93 КБ, когда UPXed) .

46
ответ дан Segfault 25 June 2009 в 11:17
поделиться
Другие вопросы по тегам:

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