|
在网上,有好多绿色软件,不仅功能强大,而且软件本身的体积非常小。有的通常
x' u# s( a( c H# u" {8 a只在几十K左右。那他们是怎么做到把软件做的怎么小的呢?现在我手把手的告诉
5 R7 ?7 C2 R( ?: X, i$ ]1 D你如何通过修改程序的编译选项来瘦身你的执行文件% F9 s5 s- n1 z0 j7 h8 L1 J
先看一个最典型的程序:
, j6 a" c! b$ n P5 d#include<stdio.h>
( Q+ ~$ I2 ]" Sint main()
" L- m+ O: b8 H) e/ D8 ]% T{
, {8 `1 K7 @1 o/ R3 R! H9 {& t( }* u printf("Hello,World");
; v, t$ o) `3 i4 d+ r5 a; a. [% M return 0;
4 ~6 \% A$ c b}3 S8 `7 {; M+ E- n# R# O
# U* Q2 a6 ~0 {* w+ Q上面的程序之所以被称之为典型,是因为他有如下的内容:" y8 u0 W) t" O3 V3 l
1、系统函数调用:printf$ v' D0 E/ K8 Q9 ^& p
2、有静态数据段$ r* q: y9 \9 T1 e
! @8 P; P+ W3 q/ a P" @9 ^好,现在把此文件放到VisualStudio6.0中进行编译,看看文件有多大。
8 \" T1 X7 y* }) V& F7 o# M( i1、用VisualStudio6.0打开HelloWorld.cpp文件,直接按F7。然后点击OK,生成
5 `2 `# T# S8 \% aProject文件,然后进行编译。编译完成了以后,看看Debug目录下的执行文件的大
' d! o, y: U6 T4 t! p8 `小,为172,096Bytes。+ `0 h' \. g+ ` r; D
* a0 @( q6 P( D& }2、刚才编译的Debug文件,现在修改成Release文件看看。选择Win32 Release,再
. S* Y$ y" ]* J9 P/ r" G: s编译。察看执行文件大小,现在成了40,960Bytes。看来Debug版本的要比Release
0 j/ Y+ s6 x" R+ W% y的小。; A8 z. r' |7 H9 n- b
6 p5 |3 G4 `- S( a2 W3 Y
3、检查代码优化:发现执行文件的优化是Maximize Speed。那么修改成Minimize
1 K U1 w" g5 W) X5 M' u3 ^Size看看。重新编译,得到执行文件的大小为:40,960Bytes。看来大小没什么变' Y/ B! M" r7 C
化。其实这是由于我们的代码本身太小的缘故,导致即使变化了也看不出来。
- T }- j/ {0 R: R4 }4 y( f' z* u$ O+ V0 I0 ~- g
4、想想我们程序的main函数是由CRT类库进行引导的。在我们现在的设定当中,由
+ S; [% [, B' `4 d于采取的是系统缺省的编译连接方式(缺省为编译为Single Thread,Static w* k" @ B+ R! Z: F
Library),所以,在我们的执行文件当中,包含了CRT的二进制代码。好,修改编' _0 c# @( N8 Z$ i
译选项:C/C++ => Category:Code Generation => Use run-time \$ }$ o+ S4 b
library:MutiThreaded Dll。编译看看:执行文件大小变成了16,384Bytes。
/ M, }$ ]* L% ^1 P: s+ {
0 {$ c1 Y7 G# Z/ _% |5、刚才的设定确实不错,一下子把执行文件大小减小到了16K。现在用UltraEdit
- c- q q3 R) `; j |看看执行文件都是些什么内容。结果大吃一惊:基本上都是0。看来这个有减小的
4 I8 g5 q6 F- r2 e( N- l |必要了。都知道,执行文件都有自己的代码段,数据段等等,每个段的大小也是采
% \9 t3 N% y. t# f8 y用编译器缺省设定的。好,我们来修改一下段的大小看看:0 U1 a" L% ~' Z2 ^; {3 b- F* K
5.1 连接选项中有一个是/opt:nowin98,意思是将段的大小设定成为Win2000适应9 b7 P( h+ H& F [6 M1 r
的。编译看看:哇塞,变成了2,560byte。看来这个选项确实把文件变小了N多。$ |. ^2 A3 Q% X% `" v
5.2 在查察连接选项中还有没有什么特别的。发现/align:xx还可以将段大小缩
" ~6 i% f9 b* H; z5 Y$ w小。通过UltraEdit察看刚才/opt:nowin98编译出来的文件,发现每个段的大小都
" R. t ~( O+ n! T7 h9 z是4K的整数倍。看来/align:xx还有减小的趋势。试一把再说:添加连接选项:0 F: B4 v5 T, t
/align:16(这个大小已经是能够设定的最小的了)。看看结果:1,408Bytes。厉
i G8 J) K3 o9 q9 U( Y" y! B. Q害,现在代码更小了。" E6 |# d. @& \- ^8 _
5.3 现在回想起来,执行文件大小有数据段,执行代码段等等,如果把这些段都合
) \8 Z1 |+ q: n% s- V8 t并起来,是不是就会把段之间的冗余有减小了呢?再试试看:添加选项:1 T% I& j/ E3 j2 |4 F
/merge:.data=.text /merge:.rdata=.text。再看看文件大小:1,328bytes。真的
: F4 k% |8 M# z% V0 t很不错了。* Z' J' ~+ Y" z0 v- I* Y
& U( V/ [0 G/ F% w# I5 \& ~: g. R9 {( M
6、刚才的设定确实不错,似乎达到了我们想要的极限了。但是回头想一下,如果+ w! h8 o$ C1 [( x6 x2 N
没有CRT库的话,会不会更小了?实际上确实这样。添加连接选项: /entry:, ?' t P: c+ P- V% {3 e" {. h
main,把入口地址直接指向我们的main函数看看。得到592Bytes。! X3 Z% T" M' K3 B
5 q0 l7 ?* ]9 E! a i/ |# _最终我们得到我们最后的大小592Bytes了。我想这也许是我们通过编译器能够编译: ]5 I% ~# Y4 `! o* f$ ?2 F
出来的最小的代码了。( G# L; `0 Q4 v* w8 Z* D% O$ Y
4 [$ G; \# d C$ r J& q+ F! F3 O& [结论:7 I6 _1 ]0 i) ] Q) F
通过上述的步骤,我们了解了如何修改那些编译连接选项来达到执行文件瘦身的目
, v, ]6 _1 l& ?8 b$ H的。但是,通常来讲,在我们的Release文件当中,并不需要如此小的执行文件。
6 \ U z! L9 D ^& G如果想达到瘦身的目的,修改为library:MutiThreaded Dll和添加/opt:nowin98已0 T& `6 n/ s/ p) G* U' S* Z
经是很好的选择了。其他别的选项在编译的时候或多或少的有警告出现,而且,带( N8 M( l6 }: z. S0 P0 m i
有那些编译选项编出来的执行文件也不一定在各个平台上能够适用。
: }8 A6 F6 f+ z7 t- N9 l7 |' R d2 h" ~3 M0 P# J e1 Z. _+ k
另外:如果你的执行文件即使通过了这些设定还是比较大的话,也可以通过一些, Y8 g L5 O/ C7 }
EXE文件压缩工具来进行压缩。比如UPX等等。在此不再细说了。
" J$ t$ f) P5 L! M& t
( {5 X. @- d, b, A) t5 j以上部分的不足之处,还请多多指正。 |
|