GCC C++“你好世界"程序->.exe 在 Windows 上编译时有 500kb 大.我怎样才能减小它的大小? [英] GCC C++ "Hello World" program -> .exe is 500kb big when compiled on Windows. How can I reduce its size?

查看:23
本文介绍了GCC C++“你好世界"程序->.exe 在 Windows 上编译时有 500kb 大.我怎样才能减小它的大小?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我最近才开始学习 C++ - 我在 Windows 上使用 nuwen's 版本的 MingW,使用 NetBeans 作为一个 IDE(我也有 MSVC 2008 的 MSDN AA 版本,虽然我不经常使用它).

编译这个简单的程序时:

#include 使用命名空间标准;int狗,猫,鸟,鱼;void f(int pet) {cout<<宠物 ID 号:" <<宠物<<结束;}int main() {输入 i, j, k;cout<<"f():" <<(长)&f <<结束;cout<<狗:" <<(长)&dog <<结束;cout<<猫:" <<(长)&cat <<结束;cout<<鸟:" <<(长)&bird <<结束;cout<<鱼:"<<(长)&鱼<<结束;cout<<我:"<<(长)&i <<结束;cout<<j:"<<(长)&j <<结束;cout<<k:"<<(长)&k <<结束;}///:~

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

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

解决方案

这里的问题不在于图书馆,而在于
库已链接.当然,iostream 是一个中等规模的库,但我没有
认为它可以如此巨大以至于导致程序生成一个可执行文件
900KB 比使用 C 函数的类似程序大.罪魁祸首
不是 iostream 而是 gcc.更准确地说,应该归咎于静态链接.

你会如何解释这些结果(用你的程序):

g++ test.cpp -o test.exe 大小:935KBgcc test.cpp -o test.exe -lstdc++ 大小:64.3KB

不同大小的可执行文件正在以完全相同的方式生成
构建选项.

答案在于 gcc 链接目标文件的方式.
当您比较这两个命令的输出时:

g++ -v test.cpp -o test.exe//使用流函数的c++程序gcc -v test.c -o test.exe//使用printf的c程序

你会发现它们唯一不同的地方(除了通往
临时目标文件)在使用的选项中:

 C++(iostream) |C(标准音频)--------------------------------Bstatic |(不在那里)-lstdc++ |(不在那里)-Bdynamic |(不在那里)-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
就我而言.我通过使用 -Bdynamic 获得了 4.5KB-O 标志
以及您的应用程序离不开的最重要的库,即
-lmingw32-lmsvcrt-lkernel32.你会得到一个25KB的可执行文件
观点.将其剥离到 10KBUPX4.5KB-5.5KB 左右.

这是一个可以玩的 Makefile,用于踢球:

## 这个 makefile 包含 GCC 传递给链接器的所有选项##当你这样编译时:gcc test.cpp -o test.exeCC=gcc## 注意:您只能将 OPTIMAL_FLAGS 与 -Bdynamic 选项一起使用.你会得到一个## 全屏错误,如果您尝试这样的操作:make minimum type=staticOPTIMAL_FLAGS=-lmingw32 -lmsvcrt -lkernel32DEFAULT_FLAGS=$(OPTIMAL_FLAGS) -lmingw32 -lgcc -lmoldname -lmingwex -lmsvcrt -ladvapi32 -lshell32 -luser32 -lkernel32 -lmingw32 -lgcc -lmoldname -lmingwex -lmsvcrtLIBRARY_PATH=-LC:MinGW32libgccmingw324.7.1-LC:mingw32libgcc-LC:mingw32libmingw32lib-LC:mingw32libOBJECT_FILES=C:MinGW32libcrt2.oC:MinGW32libgccmingw324.7.1crtbegin.oCOLLECT2=C:MinGW32libexecgccmingw324.7.1collect2.exe普通的:$(CC) -c test.cpp$(COLLECT2) -Bdynamic $(OBJECT_FILES) test.o -B$(type) -lstdc++ -Bdynamic $(DEFAULT_FLAGS) $(LIBRARY_PATH) -o test.exe优化:$(CC) -c -O test.cpp$(COLLECT2) -Bdynamic $(OBJECT_FILES) test.o -B$(type) -lstdc++ -Bdynamic $(DEFAULT_FLAGS) $(LIBRARY_PATH) -o test.exe最小:$(CC) -c -O test.cpp$(COLLECT2) -Bdynamic $(OBJECT_FILES) test.o -B$(type) -lstdc++ -Bdynamic $(OPTIMAL_FLAGS) $(LIBRARY_PATH) -o test.exe最终的:$(CC) -c -O test.cpp$(COLLECT2) -Bdynamic $(OBJECT_FILES) test.o -B$(type) -lstdc++ -Bdynamic $(OPTIMAL_FLAGS) $(LIBRARY_PATH) -o test.exe试纸.exeupx测试.exe干净的:删除 *.exe *.o

结果(YMMV):

//未以任何方式剥离或压缩使正常类型=静态大小:934KB使正常类型=动态大小:64.0KB使优化类型=动态大小:30.5KB使优化类型=静态大小:934KB使最小类型=静态(由于遗漏库导致的链接器错误)使最小类型=动态大小:25.6KB//剥离和升级使最终类型=动态(UPXed 从 9728 字节到 5120 字节 - 52.63%)使最终类型=静态(由于遗漏库导致的链接器错误)

在默认构建选项中包含 -Bstatic 的可能原因
是为了更好的表现.我尝试使用 -Bdynamic 构建 astyle 并得到
即使应用程序正常,速度平均也会降低 1 秒
比原始小(UPX 后为 400KB 与 93KB).

I just recently started learning C++ - I am using nuwen's version of MingW on Windows, using NetBeans as an IDE (I have also MSDN AA Version of MSVC 2008, though I don't use it very often).

When compiling this simple program:

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

my executable was about 1MB big. When I changed project configuration from Debug to Release, used -O1 -Os flags ( stripping debugging symbols along the way ), binary size was reduced from 1MB to 544KB.

I am not a "size freak", but I am just wondering - is there any way, that I could reduce .exe size even more? I just think, that 544KB is just too much for such a simple application ).

解决方案

The problem here is not so much with the library as it is with the way the
library is linked. Granted, iostream is a moderately huge library but I don't
think it can be so huge as to cause a program to generate an executable that is
900KB larger than a similar one that uses C functions. The one to blame
is not iostream but gcc. More accurately, static linking is to be blamed.

How would you explain these results(with your program):

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

Different sizes of executables are being generated with exactly the same
build options.

The answer lies in the way gcc links the object files.
When you compare the outputs from these two commands:

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

you'll find out that the only places they differ(apart from the paths to the
temporary object files) is in the options used:

   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 

You've got your culprit right there at the top. -Bstatic is the option that comes
exactly after the object file which may look something like this:

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

If you play around with the options and remove 'unnecessary' libraries,
you can reduce the size of the executable from 934KB to 4.5KB max
in my case. I got that 4.5KB by using -Bdynamic, the -O flag
and the most crucial libraries that your application can't live without, i.e
-lmingw32, -lmsvcrt, -lkernel32. You'll get a 25KB executable at that
point. Strip it to 10KB and UPX it to around 4.5KB-5.5KB.

Here's a Makefile to play with, for kicks:

## 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:MinGW32libgccmingw324.7.1 
-LC:mingw32libgcc 
-LC:mingw32libmingw32lib 
-LC:mingw32lib

OBJECT_FILES=
C:MinGW32libcrt2.o 
C:MinGW32libgccmingw324.7.1crtbegin.o

COLLECT2=C:MinGW32libexecgccmingw324.7.1collect2.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

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

A possible reason for the inclusion of -Bstatic in the default build options
is for better performance. I tried building astyle with -Bdynamic and got
a speed decrease of 1 second on average, even though the application was way
smaller than the original(400KB vs 93KB when UPXed).

这篇关于GCC C++“你好世界"程序->.exe 在 Windows 上编译时有 500kb 大.我怎样才能减小它的大小?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆