我最近刚开始学习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
功能。 一个怪
不是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
最大
在我的情况。 我得到的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:
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:
规模的主要部分从使用相当广泛的运行时库的茎。 所以,在现实生活中,你实际上是链接一个非常大的一块“死码”,如果你有这样一个简单的应用程序。
据我所知,没有连接标志跳过链接库中未使用的部分。
有两种方法,我知道的假较小的应用程序:
- 使用动态链接。 然后你的应用程序是指在动态加载库。 你仍然需要全尺寸(实际上更多),但是你有一个更小的可执行文件。
- 使用一个可执行的压缩系统。
文章来源: GCC C++ “Hello World” program -> .exe is 500kb big when compiled on Windows. How can I reduce its size?