|
|
|
在网上,有好多绿色软件,不仅功能强大,而且软件本身的体积非常小。有的通常
0 R5 o% l+ }$ q- u; Q- h只在几十K左右。那他们是怎么做到把软件做的怎么小的呢?现在我手把手的告诉' a3 V, u' x$ W
你如何通过修改程序的编译选项来瘦身你的执行文件0 B8 f8 m2 y) U; l! \
先看一个最典型的程序: - B$ c1 f% E+ E/ M* a
#include<stdio.h>( Z2 C0 W; g+ I% \% Q; x, B
int main()- s. H5 ~* k: C: u- U9 i
{& |$ n7 L0 k" @1 R) v' ]% R
printf("Hello,World");/ I( F9 m$ w' C& \+ g2 E
return 0;/ H. r, J' n) F5 o7 n0 j7 P6 _( D, w' I
}
6 W7 \& T/ b) s: P6 ?7 m& g' v; J7 {% {. q
上面的程序之所以被称之为典型,是因为他有如下的内容:, c* V# y* w% j( Q2 a
1、系统函数调用:printf7 V/ p" |( S1 a* w
2、有静态数据段! F* _3 D3 L& [! `0 O8 g
: H! R/ T/ V5 E1 U4 d好,现在把此文件放到VisualStudio6.0中进行编译,看看文件有多大。
8 r& `2 J8 [6 a& M! P6 j F1、用VisualStudio6.0打开HelloWorld.cpp文件,直接按F7。然后点击OK,生成
3 Q, e: J2 {2 X; I% |/ JProject文件,然后进行编译。编译完成了以后,看看Debug目录下的执行文件的大
. d0 e. ?+ e! E ^3 S小,为172,096Bytes。
' P3 c! u( J, `3 }8 S
3 R2 j9 g* S, u4 c! c+ o2、刚才编译的Debug文件,现在修改成Release文件看看。选择Win32 Release,再
; q" Z, S3 b+ \: j编译。察看执行文件大小,现在成了40,960Bytes。看来Debug版本的要比Release
7 K0 d6 V" ?6 A的小。3 X+ C! _# R m' V* C- Y8 A) |
+ K- z# T9 c' `/ r
3、检查代码优化:发现执行文件的优化是Maximize Speed。那么修改成Minimize
( n3 G3 }+ B" [- Z* n9 c4 ]Size看看。重新编译,得到执行文件的大小为:40,960Bytes。看来大小没什么变% P) U! y1 c. Q9 }5 G' M: n
化。其实这是由于我们的代码本身太小的缘故,导致即使变化了也看不出来。( u. h% h2 }# r4 ~9 k$ | r
( j% P6 }0 p4 s' E/ Y: n; D- u
4、想想我们程序的main函数是由CRT类库进行引导的。在我们现在的设定当中,由
: @+ [- b/ X* p$ x+ o) X* q于采取的是系统缺省的编译连接方式(缺省为编译为Single Thread,Static
" V( I$ X4 g/ o( Q) cLibrary),所以,在我们的执行文件当中,包含了CRT的二进制代码。好,修改编( g) N: ?. r8 N. U7 v2 q6 t
译选项:C/C++ => Category:Code Generation => Use run-time
' W1 v3 c3 n5 |, Dlibrary:MutiThreaded Dll。编译看看:执行文件大小变成了16,384Bytes。/ S5 g% f2 A v* K$ O
% U8 K* j% H$ x+ D& E) G: b( [' m
5、刚才的设定确实不错,一下子把执行文件大小减小到了16K。现在用UltraEdit
0 D S* E; y& [3 J看看执行文件都是些什么内容。结果大吃一惊:基本上都是0。看来这个有减小的$ F1 s$ T" I3 F5 w& N- f
必要了。都知道,执行文件都有自己的代码段,数据段等等,每个段的大小也是采+ g# ?& L7 B. ]( @8 Y& j# Z
用编译器缺省设定的。好,我们来修改一下段的大小看看:
L8 _* q( s# ~, w+ ^( K b% Y5.1 连接选项中有一个是/opt:nowin98,意思是将段的大小设定成为Win2000适应
1 O- w8 H" D3 X3 i1 `9 N. j的。编译看看:哇塞,变成了2,560byte。看来这个选项确实把文件变小了N多。
5 _$ [) B5 s. ]- A5.2 在查察连接选项中还有没有什么特别的。发现/align:xx还可以将段大小缩4 D1 H. o& e1 Y. j
小。通过UltraEdit察看刚才/opt:nowin98编译出来的文件,发现每个段的大小都
& Q& o) C* Q. R; A# }是4K的整数倍。看来/align:xx还有减小的趋势。试一把再说:添加连接选项:- C$ |9 }( R3 h2 P- v) k- r) A' L' E
/align:16(这个大小已经是能够设定的最小的了)。看看结果:1,408Bytes。厉
0 E: V" g2 ~7 ]9 s; A害,现在代码更小了。8 ~- o- E# L, c, x3 B% F" z
5.3 现在回想起来,执行文件大小有数据段,执行代码段等等,如果把这些段都合+ d1 Y0 n* z7 X/ k1 H. N4 d# P
并起来,是不是就会把段之间的冗余有减小了呢?再试试看:添加选项:0 r6 z' `+ t0 h+ z; K4 ~) O& S
/merge:.data=.text /merge:.rdata=.text。再看看文件大小:1,328bytes。真的+ X$ w1 p$ s7 L( k, |
很不错了。 u y' p$ o0 f6 g* J
/ \" D" B n2 B0 W6、刚才的设定确实不错,似乎达到了我们想要的极限了。但是回头想一下,如果- G% {+ _) W0 u) S- t. H
没有CRT库的话,会不会更小了?实际上确实这样。添加连接选项: /entry:9 c: A1 v/ t. f* K2 P! B6 }
main,把入口地址直接指向我们的main函数看看。得到592Bytes。" z* i% m7 e9 A l& g& p, N
: A6 `* D% e P" T9 V最终我们得到我们最后的大小592Bytes了。我想这也许是我们通过编译器能够编译
% E) i- R; y" M3 `+ R1 h出来的最小的代码了。+ k; t+ H* x( U
7 N, l, w" v; @
结论:
6 Z( g0 v+ z+ f% M通过上述的步骤,我们了解了如何修改那些编译连接选项来达到执行文件瘦身的目
. {+ L2 }: _7 h, V的。但是,通常来讲,在我们的Release文件当中,并不需要如此小的执行文件。. e+ z/ n6 O# {
如果想达到瘦身的目的,修改为library:MutiThreaded Dll和添加/opt:nowin98已* G6 W) y5 x0 F5 f5 R
经是很好的选择了。其他别的选项在编译的时候或多或少的有警告出现,而且,带% G, z. j4 Y0 J3 O! K' @! Y
有那些编译选项编出来的执行文件也不一定在各个平台上能够适用。+ k7 N1 t6 p, `$ l
, L: ?, K4 S& z ^$ v+ q另外:如果你的执行文件即使通过了这些设定还是比较大的话,也可以通过一些- A+ ^5 x. d# @, w! {
EXE文件压缩工具来进行压缩。比如UPX等等。在此不再细说了。
6 S; v1 K. B) I
5 M7 j7 f! N9 ]5 z/ s以上部分的不足之处,还请多多指正。 |
|