GCC C ++“Hello World”程序 - 在Windows上进行编译时> .exe

2019-05-13 18:55发布

我最近刚开始学习C ++ -我使用nuwen的 Windows上MingW平台版本,使用NetBeans作为IDE(我有2008 MSVC也MSDN AA版本,虽然我不经常使用它)。

当编译这个简单程序:

#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;
} ///:~

我的可执行大约1MB大。 当我改变了从调试项目配置为Release,使用-O1 -Os标志(剥离沿途调试符号),二进制文件大小从1MB减少到544KB。

我不是一个“怪胎大小”,但我只是想知道 - 有什么办法,我可以更加减少.EXE大小? 我只是觉得,这544KB实在太多这样一个简单的应用程序)。

Answer 1:

#include <iostream>

引起了很多标准库的要被链接在至少使用g ++。 如果你真的关心可执行文件的大小,请尝试更换用printf或者类似的输入输出流的所有用途。 这通常给你一个更小,更快的可执行文件(我有你的下降到约6K)在便利性和类型安全的成本。



Answer 2:

这里的问题是没有这么多的图书馆,因为它是与方式
库被链接。 诚然,iostream都是中等巨大的图书馆,但我不知道
认为它可以是如此巨大,以导致程序生成可执行即
900KB比使用类似的一个较大的C功能。 一个怪
不是iostreamgcc 。 更准确的说, 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 ....

如果你玩的选项,并删除“不必要”库,
你可以从减少可执行文件的大小934KB4.5KB最大
在我的情况。 我得到的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秒的速度下降,即使应用程序是这样
比原来的(400KB VS 93KB时UPXed)小。



Answer 3:

不知道它会使用多少给你,但有人已经做了不少工作,减少一个简单的Windows .exe文件的大小 。

他们能够创建一个简单的.exe文件将在133个字节一个现代版本的Windows上执行,通过使用一些非常极端的方法。



Answer 4:

你可以使用-s,我相信这是内置到MinGW的为好。 上的cygwin使用克++编译3.4.4简单的Hello World程序产生可执行这是476872个字节,-s再次编译(剥离不必要的数据),降低了相同的可执行到276480个字节。

使用克++ 4.3.2 cygwin的相同的Hello World应用程序产生的16495个字节的可执行文件,使用带材的尺寸减小到4608个字节。 据我所看到的,可能是最好用最新克++版本。

MingW平台刚刚发布了GCC 4.4.0,因此,如果可执行文件的大小是很重要的话,我会考虑使用。 因为它表明-s可能会帮助很大条的调试信息为你,这只是建议,如果是用于生产。



Answer 5:

你得到的C ++标准库,和其他的东西我想,静态链接作为MinGW的有自己实现这些库。

不要太在乎它,当你做出更复杂的程序,规模也不会相应增长。



Answer 6:

基本上,有没有真的什么可以做,以减少.EXE大小使用MinGW的基地分布。 550KB约小到你可以得到它,因为MinGW和GCC / G ++一般是在剥离未使用的功能不好。 关于这530KB从msvcrt.a库。

如果你真的想进入它,你可能能够重建与-ffunction截面-fdata截面编译器选项msvcrt.a库,然后用-Wl, - GC-部分连接选项将您的应用程序时,这应该能够剥夺了很多的东西离开那里。 但是,如果你刚开始学习C ++,重建该库可能有点先进。

或者你可以只使用MSVC,这是在剥离未使用的功能很大。 用MSVC编译的代码相同的位产生一个10KB的exe。



Answer 7:

那么当您使用C ++标准库,EXE可以得到很大的真的很快。 如果剥离调试符号后,你仍然希望减少软件的大小,你可以像使用封隔器UPX 。 但是,被警告,一些杀毒呛EXE挤满了UPX一些病毒在很久以前使用过它。



Answer 8:

你总是可以运行UPX对你的EXE你已经创建后。



Answer 9:

如果你使用了“纳米”实用程序或其他程序,显示什么在您的.exe,你会看到它包含吨,有人可能想使用类,但你不知道。



Answer 10:

我复制使用Cygwin和g ++测试。 您的代码编译为480K与-02。 上的可执行运行它降低到280K。

总的来说,虽然,我怀疑你的问题是使用<iostream的>头的。 这将导致一个相当大的库中进行链接。另外,还要注意cout << x不仅仅可以打印多很多。 有语言环境和溪流和各种下引擎罩的东西。

但是,如果具有小的可执行文件的大小是一个真正的,关键任务的目标,那么避免它和使用printf或者看跌期权。 如果不是,那么我会说的iostream支付的一次性费用,并用它做。



Answer 11:

如果您需要小的可执行文件,微型C将编译一个printf一个1536个字节的可执行文件(“世界,你好!”)TinyC仅仅是C,不是C ++,被称为编译效率,并提供更慢的可执行程序比GCC。

编辑:我刚才试了COUT <的“Hello World!” 在DEVC ++(束MINGW 4.8和IDE)和我得到4,5- MB可执行!!



Answer 12:

它是如何,其他的编译器像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的链接阶段去除死代码?



Answer 13:

规模的主要部分从使用相当广泛的运行时库的茎。 所以,在现实生活中,你实际上是链接一个非常大的一块“死码”,如果你有这样一个简单的应用程序。

据我所知,没有连接标志跳过链接库中未使用的部分。

有两种方法,我知道的假较小的应用程序:

  1. 使用动态链接。 然后你的应用程序是指在动态加载库。 你仍然需要全尺寸(实际上更多),但是你有一个更小的可执行文件。
  2. 使用一个可执行的压缩系统。


文章来源: GCC C++ “Hello World” program -> .exe is 500kb big when compiled on Windows. How can I reduce its size?