|
|
|
在网上,有好多绿色软件,不仅功能强大,而且软件本身的体积非常小。有的通常
, p" n+ b. W: }. q, X: ]只在几十K左右。那他们是怎么做到把软件做的怎么小的呢?现在我手把手的告诉
4 B5 p: Y6 u0 c) |( @你如何通过修改程序的编译选项来瘦身你的执行文件
( `1 k4 S' g' _; D n. e先看一个最典型的程序:
2 x* C- r" j# m4 j- V5 H2 m5 R#include<stdio.h>( ^1 o) f8 q* }1 t# A. u- @8 R# w
int main()
+ W* R7 O" f' W) F! b{' Z% B. H& h0 A2 A* j; j: ~* e0 {
printf("Hello,World");
: X$ @7 @4 }# \0 M7 d" g+ O return 0;
( H( Q, k' `- W" O( v}9 a* X2 N$ d# r; M7 N$ n. h. G* Z
2 i5 j2 W% Q) O) Q上面的程序之所以被称之为典型,是因为他有如下的内容:
: K5 {& M- m( i; Y# @$ R9 T1、系统函数调用:printf
; v8 z* K- [4 F9 D2、有静态数据段
2 r; ]8 c9 V5 t5 @6 X1 R
3 Y/ J ?( n, l; \, d好,现在把此文件放到VisualStudio6.0中进行编译,看看文件有多大。3 Q. p5 C- ~8 s
1、用VisualStudio6.0打开HelloWorld.cpp文件,直接按F7。然后点击OK,生成
9 ?' `; j; H& \" R* f8 l- I8 OProject文件,然后进行编译。编译完成了以后,看看Debug目录下的执行文件的大5 K, d5 \2 o. l1 p( V
小,为172,096Bytes。
$ W. H i% P, r& ]. x; B
% I# j4 p1 f4 ~# d c2、刚才编译的Debug文件,现在修改成Release文件看看。选择Win32 Release,再
$ m, a0 ^3 u5 k9 Y: h9 ^) C" E编译。察看执行文件大小,现在成了40,960Bytes。看来Debug版本的要比Release
: j" q) P* |: r( U/ F3 v的小。
6 j/ b8 Z R7 x! w& m: d, @1 W% h* A, c# m8 U( o& e8 H$ d
3、检查代码优化:发现执行文件的优化是Maximize Speed。那么修改成Minimize: }: y" E7 |4 _4 x3 k! s
Size看看。重新编译,得到执行文件的大小为:40,960Bytes。看来大小没什么变% \, n# I, X$ |/ J; ^! [3 K
化。其实这是由于我们的代码本身太小的缘故,导致即使变化了也看不出来。
( s K) }. r( O. y
6 l4 L- `+ |& u4 l4 ^( c' K4、想想我们程序的main函数是由CRT类库进行引导的。在我们现在的设定当中,由
7 T8 s6 `( Y* S# l于采取的是系统缺省的编译连接方式(缺省为编译为Single Thread,Static7 K9 Y9 v |$ D. [; ]
Library),所以,在我们的执行文件当中,包含了CRT的二进制代码。好,修改编' @9 s" m" ^7 C. ~, \3 M
译选项:C/C++ => Category:Code Generation => Use run-time
+ q! C8 M f: h8 N2 z7 j6 Y$ vlibrary:MutiThreaded Dll。编译看看:执行文件大小变成了16,384Bytes。; c7 j& K+ i# k5 \% G& V4 H
" W M+ M& G. D2 [4 j7 Q5、刚才的设定确实不错,一下子把执行文件大小减小到了16K。现在用UltraEdit, c$ D* c! v8 s
看看执行文件都是些什么内容。结果大吃一惊:基本上都是0。看来这个有减小的
- q1 J( U1 z/ G0 a2 L7 t1 U必要了。都知道,执行文件都有自己的代码段,数据段等等,每个段的大小也是采
t6 Q) J- h: p/ v: t9 g2 ^用编译器缺省设定的。好,我们来修改一下段的大小看看:
5 V( w% o& t" S! S7 C5.1 连接选项中有一个是/opt:nowin98,意思是将段的大小设定成为Win2000适应; M* T& ]/ C# ]- w
的。编译看看:哇塞,变成了2,560byte。看来这个选项确实把文件变小了N多。
; P4 _- W O+ ~7 C* |- N5.2 在查察连接选项中还有没有什么特别的。发现/align:xx还可以将段大小缩! l& N( a) G V' C% m# L" S
小。通过UltraEdit察看刚才/opt:nowin98编译出来的文件,发现每个段的大小都
+ z8 q; d3 |+ \* _是4K的整数倍。看来/align:xx还有减小的趋势。试一把再说:添加连接选项:; ^2 z+ ]9 j2 u8 ?0 Y+ |
/align:16(这个大小已经是能够设定的最小的了)。看看结果:1,408Bytes。厉
8 n1 L% M$ i% t* |# N害,现在代码更小了。
# L5 a; n" ?2 P0 A [( K( ?" X, D5.3 现在回想起来,执行文件大小有数据段,执行代码段等等,如果把这些段都合
2 J$ }/ e M F! T6 v" }并起来,是不是就会把段之间的冗余有减小了呢?再试试看:添加选项:5 D0 I# B2 s; |/ \$ R( g
/merge:.data=.text /merge:.rdata=.text。再看看文件大小:1,328bytes。真的9 }, S3 T( M" a# F$ h
很不错了。
& \0 G5 }; H/ s- G
2 _# a/ ]; i6 C) v$ N3 l! [6、刚才的设定确实不错,似乎达到了我们想要的极限了。但是回头想一下,如果* x- h+ l- Y# Y, n- g9 |; x
没有CRT库的话,会不会更小了?实际上确实这样。添加连接选项: /entry:; S4 _* e( B h7 ~; T
main,把入口地址直接指向我们的main函数看看。得到592Bytes。
$ Y7 m/ c/ ]3 d: N( }/ Y+ u: i8 r2 R: \$ ~8 u8 \
最终我们得到我们最后的大小592Bytes了。我想这也许是我们通过编译器能够编译
7 u# c: Y" `/ z& G. }出来的最小的代码了。# c: w% j: i0 w: `& Y B
% D; V/ f$ F9 b
结论:: ^/ E7 s2 ^7 M* B' n
通过上述的步骤,我们了解了如何修改那些编译连接选项来达到执行文件瘦身的目
( z/ u4 ~: y" X" c+ L的。但是,通常来讲,在我们的Release文件当中,并不需要如此小的执行文件。: k- R; |9 l) F2 w9 S
如果想达到瘦身的目的,修改为library:MutiThreaded Dll和添加/opt:nowin98已
/ ^- I: `+ i3 r9 [: E) I$ D" a3 v经是很好的选择了。其他别的选项在编译的时候或多或少的有警告出现,而且,带! h- \! r7 }# h% ~2 N5 v3 n* |
有那些编译选项编出来的执行文件也不一定在各个平台上能够适用。
8 Q/ L/ w! K! o7 @& z! U
: }8 b2 R! }$ u3 f' w l另外:如果你的执行文件即使通过了这些设定还是比较大的话,也可以通过一些9 u9 A3 l N; I# b: H
EXE文件压缩工具来进行压缩。比如UPX等等。在此不再细说了。
1 P1 t& B8 @, n' c" _, Q, s& z
9 d( i- N+ @) d以上部分的不足之处,还请多多指正。 |
|