programa “Olá Mundo” GCC C ++ -> .exe é 500kb grande quando compilado no Windows. Como posso reduzir o seu tamanho?

StackOverflow https://stackoverflow.com/questions/1042773

Pergunta

Eu só recentemente começou a aprender C ++ - Eu estou usando versão de nuwen de MingW no Windows, usando o NetBeans como um IDE (eu tenho também MSDN AA Versão do MSVC 2008, embora eu não usá-lo muito frequentemente).

Ao compilar este programa simples:

#include <iostream>
using namespace std;

int dog, cat, bird, fish;

void f(int pet) {
  cout << "pet id number: " << pet << endl;
}

int main() {
  int i, j, k;
  cout << "f(): " << (long)&f << endl;
  cout << "dog: " << (long)&dog << endl;
  cout << "cat: " << (long)&cat << endl;
  cout << "bird: " << (long)&bird << endl;
  cout << "fish: " << (long)&fish << endl;
  cout << "i: " << (long)&i << endl;
  cout << "j: " << (long)&j << endl;
  cout << "k: " << (long)&k << endl;
} ///:~

meu executável foi de cerca de 1MB grande. Quando eu mudei configuração do projeto de Debug Release , usado -o1 -os bandeiras (decapagem depuração símbolos ao longo do caminho), tamanho do binário foi reduzido de 1MB para 544KB.

Eu não sou um "freak tamanho", mas eu estou apenas perguntando - existe alguma maneira, que eu poderia reduzir .exe tamanho ainda mais? Eu só acho que 544KB é muito pouco para tal aplicação simples).

Foi útil?

Solução

O

#include <iostream>

faz com que um monte de biblioteca padrão para ser ligado em, pelo menos, com g ++. Se você está realmente preocupado com o tamanho executável, tente substituir todos os usos de iostreams com printf ou similar. Isto irá normalmente dar-lhe uma menor, mais rápido executável (I tem o seu baixo para cerca de 6K) ao custo de conveniência e tipo de segurança.

Outras dicas

O problema aqui não é tanto com a biblioteca, pois é com a forma como o
biblioteca está ligada. Concedido, iostream é um moderado enorme biblioteca, mas eu não
acho que pode ser tão grande como para causar um programa para gerar um executável que é
900KB maior do que um similar que os usos C funções. O único culpado
não é iostream mas gcc. Mais precisamente, static linking deve ser responsabilizado.

Como você explicaria esses resultados (com seu programa):

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

Diferentes tamanhos de executáveis ??estão sendo gerados com exatamente o mesmo
opções de compilação.

As mentiras resposta na forma gcc liga os arquivos objeto.
Quando você compara as saídas destes dois comandos:

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

Você vai descobrir que a única coloca eles diferem (além dos caminhos para o
arquivos de objetos temporários) está nas opções utilizadas:

   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 

Você tem o seu culpado ali mesmo no topo. -Bstatic é a opção que vem
exatamente após o arquivo de objeto que pode ser algo como isto:

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

Se você brincar com as opções e remover bibliotecas 'desnecessárias',
você pode reduzir o tamanho do executável a partir 934KB para 4.5KB max
No meu caso. Eu tenho que 4.5KB usando -Bdynamic, o -O flag e os a maioria das bibliotecas cruciais que a sua aplicação não pode viver sem, ou seja
-lmingw32, -lmsvcrt, -lkernel32. Você vai ter um 25KB executável em que
ponto. Tira-lo para 10KB e UPX -lo para cerca de 4.5KB-5.5KB.

Aqui está um Makefile para brincar, para pontapés:

## 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

Resultados (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)

Uma possível razão para a inclusão de -Bstatic no padrão opções de construção
é para melhor desempenho. Eu tentei construir astyle com -Bdynamic e tem
uma diminuição da velocidade de um segundo, em média, mesmo que o aplicativo foi maneira
menor que o original (400KB vs 93KB quando UPXed).

Não tenho certeza quanto o uso será para você, mas alguém fez um monte de trabalho sobre a redução do tamanho de um Windows simples .exe .

Eles foram capazes de criar um .exe simples que irá executar em uma versão moderna do Windows em 133 bytes, usando alguns métodos muito extremas.

Você pode usar -s, que eu acredito que é construído em mingw também. A aplicação mundial simples Olá compilada usando g ++ 3.4.4 na CYGWIN produzido executável que era 476872 bytes, que compilam novamente com -S (tiras de dados desnecessários), reduzida a mesma executável para 276480 bytes.

O mesmo pedido Olá mundo em cygwin usando g ++ 4.3.2 produzido um executável de 16495 bytes, utilizando tira reduziu o tamanho de 4608 bytes. Tanto quanto eu posso ver, provavelmente melhor para usar a versão mais recente do g ++.

MingW acaba de lançar gcc 4.4.0, por isso, se o tamanho do executável é importante, então eu consideraria usar isso. Como indica -s provavelmente ajuda tira muita da informação de depuração para fora para você, que é recomendada apenas se for para uso em produção.

Você começa a biblioteca C ++ padrão, e outras coisas que eu acho que, estaticamente ligado em como mingw tem a sua própria implementação dessas bibliotecas.

Não se preocupe muito sobre isso, quando você faz programa mais complexo, o tamanho não vai crescer em conformidade.

Basicamente, não há realmente qualquer coisa que você pode fazer para reduzir esse tamanho .exe com uma distribuição base de mingw. 550kb é quase tão pequeno como você pode obtê-lo, porque mingw e gcc / g ++ em geral são ruins em descascar funções não utilizadas. Sobre 530KB de que é a partir da biblioteca msvcrt.a.

Se você realmente queria para chegar a ele, você pode ser capaz de reconstruir a biblioteca msvcrt.a com opções -ffunction-seções -fdata-seções do compilador, e depois usar o -Wl, - GC-seções opções vinculador quando ligando sua aplicação, e este deve ser capaz de tirar um monte de coisas fora de lá. Mas se você está começando a aprender C ++, a reconstrução que a biblioteca pode ser um pouco avançado.

Ou você pode simplesmente usar MSVC, que é grande em descascar funções não utilizadas. Nesse mesmo pedaço de código compilado com MSVC produz um exe 10kb.

Bem, quando você usar a biblioteca padrão C ++, exe pode obter grandes muito rapidamente. Se após a remoção de símbolos de depuração, você ainda quer reduzir o tamanho do seu software, você pode usar um empacotador como UPX . Mas, ser avisado, alguns choke antivírus em exe embalado com UPX como alguns vírus utilizado ele há muito tempo.

Você pode sempre executar UPX em seu exe depois de ter criado-lo.

Se você usar o utilitário "nm" ou algum outro programa que mostra o que está em seu .exe, você verá que ele contém toneladas de classes que alguém pode quiser usar, mas que você não.

Eu replicado o teste usando Cygwin e g ++. Seu código compilado para 480k com -O2. Correndo tira no executável reduziu a 280k.

Em geral, porém, eu suspeito que o seu problema é o uso do cabeçalho. Isso faz com que um bastante grande biblioteca a ser vinculado. Também, nota que cout << x faz muito mais do que apenas a impressão. Há locais e córregos e todos os tipos de coisas sob o capô.

Se, no entanto, ter um pequeno tamanho do executável é um real, objetivo de missão crítica, então evitá-lo e usar printf ou puts. Se não for, então eu diria que pagar o custo de um tempo de iostream e ser feito com ele.

Se você precisar de pequenas executáveis, Tiny C irá compilar a 1536 bytes executável para um printf ( "Olá, mundo!") TinyC é somente C, não C ++ e é conhecido para compilar mais rápido e dar executáveis ??mais lento do que o gcc.

EDITADO: Eu apenas tentei um cout < "Olá mundo!" em DevC ++ (feixes Mingw 4.8 e um IDE) e eu tenho um 4,5 MB executável !!

Como é que outros compiladores como msvc8 ou mesmo um compilador de ordem como o Borland C ++ 5.5.1 são capazes de produzir executáveis ??muito pequenos, mas gcc mingw não é capaz de?

Eu fiz uma compilação rápida de um 'Olá mundo' para cada um dos seguintes conjuntos de ferramentas e observado o tamanho executável compilado. Por favor note que em todos esses casos, a biblioteca de tempo de execução é estaticamente ligados e tudo debug símbolos foram retirados:

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

O que é interessante é a versão mais recente do GCC 4.4.1 produz um executável ainda maior do que gcc3.4.5, provavelmente devido a versão diferente do libstdc ++.

Então, há realmente nenhuma maneira de remover código morto durante a fase ligando para mingw?

A maior parte do tamanho decorre do uso de bastante extensas bibliotecas de execução. Assim, na vida real você está realmente ligando um grande pedaço de 'código morto' se você tem um tal aplicação simples.

Tanto quanto eu sei que não existem bandeiras vinculador para ignorar as partes não utilizadas de uma biblioteca ligada.

Há duas maneiras que eu conheço para um falso aplicativo menor:

  1. Use a ligação dinâmica. Em seguida, sua aplicação refere-se à biblioteca carregada dinamicamente. Você ainda precisa do tamanho grande (na verdade mais), mas você tem um executável muito menor.
  2. Use um executável compressão sistema.
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top