|
|
|
在网上,有好多绿色软件,不仅功能强大,而且软件本身的体积非常小。有的通常
3 `. |+ P+ z) z' y只在几十K左右。那他们是怎么做到把软件做的怎么小的呢?现在我手把手的告诉5 x2 p& Y+ c+ g6 R' y
你如何通过修改程序的编译选项来瘦身你的执行文件' ]& q( v6 S: Z2 w: M/ v5 m7 I0 U
先看一个最典型的程序: # @& q1 b* M7 c$ W0 h$ j
#include<stdio.h> z1 x) L! P$ ]3 B" U. G( n% g! k
int main()
8 _& ~0 u, K* S( s# Q6 u- @{6 R: P' t% b) a6 T7 T7 n
printf("Hello,World");
+ W# y( O s4 H4 b return 0;
7 r) o X, _7 Z' E p. |. ~2 ]}
- U; B& S' j- R8 k1 N+ p4 g" O$ k8 m" M3 ~
上面的程序之所以被称之为典型,是因为他有如下的内容:
' H+ F5 ?0 Y) Q, t1、系统函数调用:printf
4 J- t5 S4 p6 z/ r4 Y6 j2、有静态数据段6 h/ \& ^5 [ }8 y
4 x5 l3 n$ n" r6 S) J8 j! [+ A
好,现在把此文件放到VisualStudio6.0中进行编译,看看文件有多大。7 r* S: ^, \2 V' s+ _ P
1、用VisualStudio6.0打开HelloWorld.cpp文件,直接按F7。然后点击OK,生成) K# X7 G" W6 f4 i6 y: f2 l
Project文件,然后进行编译。编译完成了以后,看看Debug目录下的执行文件的大. z+ p$ R4 P1 g. {, l
小,为172,096Bytes。
% f* a7 d+ ?( N& f: h6 f. T& z# q. }( W+ Y% ~% _6 L4 L2 ^
2、刚才编译的Debug文件,现在修改成Release文件看看。选择Win32 Release,再! t# q9 y( [4 h) Y+ d
编译。察看执行文件大小,现在成了40,960Bytes。看来Debug版本的要比Release# d0 i. p* I/ `& Z3 G& @) Z
的小。# ?" x9 i6 p' L: u: N' [0 K
( Y7 B0 V @6 \- a8 @; K
3、检查代码优化:发现执行文件的优化是Maximize Speed。那么修改成Minimize7 \/ i/ a# _* i9 p, v
Size看看。重新编译,得到执行文件的大小为:40,960Bytes。看来大小没什么变5 n3 {0 t4 u+ N# _9 T
化。其实这是由于我们的代码本身太小的缘故,导致即使变化了也看不出来。% r2 |# h8 Z6 n0 B
, q4 b, ^1 d- o3 R+ ~" I# N
4、想想我们程序的main函数是由CRT类库进行引导的。在我们现在的设定当中,由
7 C+ J1 ]: z) y& @5 q1 J. s2 r于采取的是系统缺省的编译连接方式(缺省为编译为Single Thread,Static
2 R; f1 ~6 |6 @7 \5 [Library),所以,在我们的执行文件当中,包含了CRT的二进制代码。好,修改编( w3 p; i) k. N g8 U$ R- K$ P
译选项:C/C++ => Category:Code Generation => Use run-time
! c* G- N2 L& y5 j& ?' E1 k. W9 @library:MutiThreaded Dll。编译看看:执行文件大小变成了16,384Bytes。% P$ v. `: P- e" J4 `1 H3 g
2 j) f+ f! j y, G) U l5、刚才的设定确实不错,一下子把执行文件大小减小到了16K。现在用UltraEdit+ x- n3 @" R4 }* b2 v
看看执行文件都是些什么内容。结果大吃一惊:基本上都是0。看来这个有减小的$ T! `3 \8 s: L0 }! w! G. | j
必要了。都知道,执行文件都有自己的代码段,数据段等等,每个段的大小也是采
1 l) T5 k( O- A用编译器缺省设定的。好,我们来修改一下段的大小看看:
3 u7 X3 m6 @* {& Q8 O" P0 k5.1 连接选项中有一个是/opt:nowin98,意思是将段的大小设定成为Win2000适应4 ?* v# t/ H, z+ O( K y
的。编译看看:哇塞,变成了2,560byte。看来这个选项确实把文件变小了N多。' x. j: a7 t$ P" P0 W
5.2 在查察连接选项中还有没有什么特别的。发现/align:xx还可以将段大小缩' f, B5 J: c7 @0 d
小。通过UltraEdit察看刚才/opt:nowin98编译出来的文件,发现每个段的大小都
5 N9 P: p, I% \% x是4K的整数倍。看来/align:xx还有减小的趋势。试一把再说:添加连接选项:2 ?) S8 y- T+ }/ T
/align:16(这个大小已经是能够设定的最小的了)。看看结果:1,408Bytes。厉7 X. Q: }- A8 f+ }! n
害,现在代码更小了。
9 {% f) g; e% x n) ?, [5 b y3 H5.3 现在回想起来,执行文件大小有数据段,执行代码段等等,如果把这些段都合
% Y. Z) w8 j$ c并起来,是不是就会把段之间的冗余有减小了呢?再试试看:添加选项:
; Z" |! a% C# L* L% ^/merge:.data=.text /merge:.rdata=.text。再看看文件大小:1,328bytes。真的
: @' l! z- A- |$ X7 w很不错了。
8 p. I: C0 E7 ^; c* {9 J9 j) [3 p) z' {, _" [+ f& P/ H$ i
6、刚才的设定确实不错,似乎达到了我们想要的极限了。但是回头想一下,如果
+ L& r P+ q) _6 w5 q, _6 t6 R没有CRT库的话,会不会更小了?实际上确实这样。添加连接选项: /entry:
7 P" i0 {6 p$ ]$ G! ?! gmain,把入口地址直接指向我们的main函数看看。得到592Bytes。
" e7 n: d' z0 j, l2 |# x; W. B2 B
# v4 @ m( i, Y( y最终我们得到我们最后的大小592Bytes了。我想这也许是我们通过编译器能够编译
( w$ ]3 r) l& F6 m& P q/ }( s' B x出来的最小的代码了。
( y0 { \. {# m) N- i
. f" E% Q9 R& S& r$ X: j `1 p% c结论:
4 g* B! h; b9 d& S通过上述的步骤,我们了解了如何修改那些编译连接选项来达到执行文件瘦身的目" {5 a2 F/ w2 V* D+ b
的。但是,通常来讲,在我们的Release文件当中,并不需要如此小的执行文件。
3 `! K$ a1 K- z1 |; O/ T. F如果想达到瘦身的目的,修改为library:MutiThreaded Dll和添加/opt:nowin98已
. P9 Q6 ]# A+ z经是很好的选择了。其他别的选项在编译的时候或多或少的有警告出现,而且,带
8 Z5 r) i. t4 U& }有那些编译选项编出来的执行文件也不一定在各个平台上能够适用。+ N$ n- J) _5 {/ `# L/ J' T
# f& b7 m3 c4 X3 }
另外:如果你的执行文件即使通过了这些设定还是比较大的话,也可以通过一些5 |& q; T# m8 s( A
EXE文件压缩工具来进行压缩。比如UPX等等。在此不再细说了。
, j$ w5 @& W( a c+ \/ H8 _, N4 H3 k" f+ W$ j
以上部分的不足之处,还请多多指正。 |
|