|
|
|
在网上,有好多绿色软件,不仅功能强大,而且软件本身的体积非常小。有的通常
5 j6 T/ ]+ }/ ?# e5 m+ p. Z只在几十K左右。那他们是怎么做到把软件做的怎么小的呢?现在我手把手的告诉
0 Z4 Q6 I/ Q/ F1 p4 U) Y; H9 Z你如何通过修改程序的编译选项来瘦身你的执行文件* {7 M$ f* B1 v$ w- X4 X* ^% F
先看一个最典型的程序:
, ?, B% U9 B3 W- W4 V#include<stdio.h>: S9 P* K B. H* l& C9 c. l
int main()
+ q. X5 a6 [3 U8 _/ N6 v{8 D: Y6 c3 ]7 H3 `# M$ F; J
printf("Hello,World");
# c& `" Y0 x& a0 ]5 g+ S# ~9 @" ? return 0;
B5 _$ B, x' y6 o* ]/ M}2 g; _3 A1 G, I1 k& X
5 d" `' [2 z. B$ w% s
上面的程序之所以被称之为典型,是因为他有如下的内容:5 y7 [7 y0 {4 F! |
1、系统函数调用:printf1 E1 `$ F7 Z. l- j+ J, V
2、有静态数据段 D- j2 h" ]# Y% Z3 f- i! J
' p8 F' C; A8 d好,现在把此文件放到VisualStudio6.0中进行编译,看看文件有多大。- }! H& Q* ?' a: e
1、用VisualStudio6.0打开HelloWorld.cpp文件,直接按F7。然后点击OK,生成5 P# I# F. ~- C
Project文件,然后进行编译。编译完成了以后,看看Debug目录下的执行文件的大" |% p N2 i' {
小,为172,096Bytes。8 R* G* k) |8 x' E4 q
/ R! G1 b( L/ d2、刚才编译的Debug文件,现在修改成Release文件看看。选择Win32 Release,再
( u5 k2 m5 M( A1 O0 [, w编译。察看执行文件大小,现在成了40,960Bytes。看来Debug版本的要比Release: n: J2 i2 \8 h8 o2 M" j
的小。$ `! L( d B4 Q5 p
8 Z7 O+ C" M4 h P) W3 b% w4 V
3、检查代码优化:发现执行文件的优化是Maximize Speed。那么修改成Minimize
/ ^9 r% L1 P7 V& r/ X* aSize看看。重新编译,得到执行文件的大小为:40,960Bytes。看来大小没什么变5 i/ X$ N% s$ Z; U, W7 S
化。其实这是由于我们的代码本身太小的缘故,导致即使变化了也看不出来。! Y2 c _9 ~2 t7 ~' |
$ O3 l5 G+ s7 {. t8 e1 j2 V; b4、想想我们程序的main函数是由CRT类库进行引导的。在我们现在的设定当中,由
( f" L6 R3 U1 g( v# }* ~于采取的是系统缺省的编译连接方式(缺省为编译为Single Thread,Static7 p- |6 H/ e" c: [+ f$ o9 q ~* n5 |
Library),所以,在我们的执行文件当中,包含了CRT的二进制代码。好,修改编
2 U! a8 D+ J& \" s( A0 g8 Y译选项:C/C++ => Category:Code Generation => Use run-time
p6 M; }, A& M% N& M: ]library:MutiThreaded Dll。编译看看:执行文件大小变成了16,384Bytes。; |+ L! D6 w ?
0 ~3 K H* a& z, E1 J
5、刚才的设定确实不错,一下子把执行文件大小减小到了16K。现在用UltraEdit- N- k" X/ l" [! k
看看执行文件都是些什么内容。结果大吃一惊:基本上都是0。看来这个有减小的
7 m; S y. z) P Q& H% z, @' B必要了。都知道,执行文件都有自己的代码段,数据段等等,每个段的大小也是采: {; S1 Q7 G2 B$ v: }" V
用编译器缺省设定的。好,我们来修改一下段的大小看看:
; t- D( n- ~6 P3 Q6 @5.1 连接选项中有一个是/opt:nowin98,意思是将段的大小设定成为Win2000适应& t; x" A4 y |- R! A
的。编译看看:哇塞,变成了2,560byte。看来这个选项确实把文件变小了N多。' ]; ?9 Y* Q' G, G4 a+ j) E* C( x- Q
5.2 在查察连接选项中还有没有什么特别的。发现/align:xx还可以将段大小缩
, J# g' g b. @" {) [小。通过UltraEdit察看刚才/opt:nowin98编译出来的文件,发现每个段的大小都
3 V R( j2 q: q* E) L& P+ J' M. e是4K的整数倍。看来/align:xx还有减小的趋势。试一把再说:添加连接选项:
& o( j0 E+ C6 f! Q0 l" z) h! Y/align:16(这个大小已经是能够设定的最小的了)。看看结果:1,408Bytes。厉9 c8 k* }" T6 a( W" G$ p
害,现在代码更小了。
4 l4 }' E9 _( i/ R. Q/ @5.3 现在回想起来,执行文件大小有数据段,执行代码段等等,如果把这些段都合
1 ]* Y. x h0 O9 H5 r并起来,是不是就会把段之间的冗余有减小了呢?再试试看:添加选项:
8 U8 ^) M% }; @3 A- q/merge:.data=.text /merge:.rdata=.text。再看看文件大小:1,328bytes。真的" m6 K# M/ z/ E8 S6 }7 Z5 ~
很不错了。2 @/ n! w' a) l6 L" w
+ W7 Y* Y: W' i0 O* B% d
6、刚才的设定确实不错,似乎达到了我们想要的极限了。但是回头想一下,如果
/ h& K9 S! U$ T9 v: X9 ^9 H没有CRT库的话,会不会更小了?实际上确实这样。添加连接选项: /entry:% X# H) g8 U0 ]3 u' F* B' T
main,把入口地址直接指向我们的main函数看看。得到592Bytes。
7 Z2 ]3 T6 p) w/ t) d. w0 }; @6 v% \# U$ J) B1 A3 s; Q: }
最终我们得到我们最后的大小592Bytes了。我想这也许是我们通过编译器能够编译
3 @4 Z- l- Z" M+ H) ~2 u* q出来的最小的代码了。 C$ L) `" B7 x7 x
) K( @' ?( a1 R, t6 |! b) e
结论:' Y# o% w5 z! ]& H5 H" J2 U
通过上述的步骤,我们了解了如何修改那些编译连接选项来达到执行文件瘦身的目
7 U* A; K/ ], a的。但是,通常来讲,在我们的Release文件当中,并不需要如此小的执行文件。- e# W6 l' _0 [
如果想达到瘦身的目的,修改为library:MutiThreaded Dll和添加/opt:nowin98已
. F) l- Y. s1 r3 E F6 B/ @. c经是很好的选择了。其他别的选项在编译的时候或多或少的有警告出现,而且,带
) [: g5 e! G' y有那些编译选项编出来的执行文件也不一定在各个平台上能够适用。
o) C7 @& y2 Q
" M: E0 H) T, j9 I0 m另外:如果你的执行文件即使通过了这些设定还是比较大的话,也可以通过一些
5 O% a1 Z4 Z, }( E" tEXE文件压缩工具来进行压缩。比如UPX等等。在此不再细说了。 P5 x t& a3 h Z* V9 {6 H0 _
p5 d6 z# N& q) p9 X
以上部分的不足之处,还请多多指正。 |
|