GCC C ++“ Hello World”程序-> .exe在Windows上编译时,大小为500kb。如何缩小尺寸? UPX

问题描述 投票:30回答:14

[我最近才开始学习C ++-我在Windows上使用MingW的nuwen's版本,并使用NetBeans作为IDE(我也有MSVC 2008的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。当我将项目配置从Debug更改为Release时,使用了-O1-Os标志(沿途剥离调试符号),二进制文件的大小从1MB减少到544KB。

我不是“怪胎”,但我只是想知道-有什么办法可以使.exe大小进一步减小?我只是认为,对于这样一个简单的应用程序来说,544KB实在太大了。

c++ optimization gcc netbeans size
14个回答
24
投票
#include <iostream>

至少与g ++链接了很多标准库。如果您真的担心可执行文件的大小,请尝试使用printf或类似的替代iostream的所有用法。通常,这会为您提供更小,更快的可执行文件(我将您的文件大小降低到大约6K),但会带来便利和类型安全的问题。


2
投票
strip

2
投票

1
投票

0
投票

0
投票
减小g ++ hello world二进制大小

54
投票
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,并剥离为UPX4.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秒比原始大小小(UPXed后为400KB与93KB)。


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

9
投票
使用g ++ 4.3.2在cygwin上的同一hello world应用程序生成了16495字节的可执行文件,使用strip将大小减小到4608字节。据我所知,最好使用最新版本的g ++。

MingW刚刚发布了gcc 4.4.0,因此,如果可执行文件的大小很重要,那么我会考虑使用它。如-s所示,它可能会帮助您去除很多调试信息,只有在将其用于生产时才建议使用。


8
投票

4
投票

2
投票

2
投票

2
投票
might
© www.soinside.com 2019 - 2024. All rights reserved.