|
在网上,有好多绿色软件,不仅功能强大,而且软件本身的体积非常小。有的通常
, f" _& c" X2 u& l只在几十K左右。那他们是怎么做到把软件做的怎么小的呢?现在我手把手的告诉/ p! a) D, Y3 J: @9 ^7 m5 c
你如何通过修改程序的编译选项来瘦身你的执行文件7 @/ s [; T$ l0 E+ a
先看一个最典型的程序:
( [# b x! v$ L+ w4 K#include<stdio.h>
" g2 [# ?4 f" K* U5 @+ A6 Fint main()
~3 T4 `- F0 l) ]2 L* e; _7 w1 E# n{
1 c$ u6 r/ X' e1 }$ i9 Q printf("Hello,World");& {8 I9 U: P% o$ N5 u( n" j, o- u1 j
return 0;! y# j; p; \+ S0 `! x- W) A! ?
}
U+ ]6 \' |( G; {7 q: Z
6 P0 i) j4 N3 M9 M上面的程序之所以被称之为典型,是因为他有如下的内容:8 }! o7 `3 k# T7 m2 e
1、系统函数调用:printf
8 R; t8 W; d+ h2、有静态数据段
. P- D: X/ Y) @. `0 _* ^% `2 H7 p6 y: `, x
好,现在把此文件放到VisualStudio6.0中进行编译,看看文件有多大。 V% E5 I5 I* a: f1 k: b# c. u
1、用VisualStudio6.0打开HelloWorld.cpp文件,直接按F7。然后点击OK,生成
* ]( E! T. K& O: H3 d' c: K2 X+ ?) YProject文件,然后进行编译。编译完成了以后,看看Debug目录下的执行文件的大
0 A g- q/ g+ M7 X+ B( _小,为172,096Bytes。+ D4 i' \4 | K! N. f0 Y* D& l
g2 i( G Z: n- }2、刚才编译的Debug文件,现在修改成Release文件看看。选择Win32 Release,再
; f2 N) q! y# F. i/ W& `: s+ W编译。察看执行文件大小,现在成了40,960Bytes。看来Debug版本的要比Release. A9 z, @, `) V& @$ A) D
的小。
6 {4 F" \& K+ Z1 X& f& v$ V& V( o+ s0 V0 [1 e7 g" t, ]
3、检查代码优化:发现执行文件的优化是Maximize Speed。那么修改成Minimize" C9 d4 P$ y, l8 i7 b
Size看看。重新编译,得到执行文件的大小为:40,960Bytes。看来大小没什么变
( o8 }2 A: r- ?5 w3 J% O化。其实这是由于我们的代码本身太小的缘故,导致即使变化了也看不出来。
* }; \; V! L! Z1 a( V/ `4 z5 s/ r% T" b: m b; a
4、想想我们程序的main函数是由CRT类库进行引导的。在我们现在的设定当中,由
. v% Q z0 x5 n/ i: V+ S于采取的是系统缺省的编译连接方式(缺省为编译为Single Thread,Static' N0 H" w0 L& P) N
Library),所以,在我们的执行文件当中,包含了CRT的二进制代码。好,修改编
8 w4 a9 r3 _* ], O* o- |译选项:C/C++ => Category:Code Generation => Use run-time+ n1 w! Y* G) a% q
library:MutiThreaded Dll。编译看看:执行文件大小变成了16,384Bytes。
- k( K# `5 Q" i
1 Z7 z% R7 D: j5、刚才的设定确实不错,一下子把执行文件大小减小到了16K。现在用UltraEdit$ @+ J3 E8 ^! o- P8 ^
看看执行文件都是些什么内容。结果大吃一惊:基本上都是0。看来这个有减小的
, n' |7 g! T4 O# H, X必要了。都知道,执行文件都有自己的代码段,数据段等等,每个段的大小也是采# ]+ Y' ~" z+ K; C/ l: z
用编译器缺省设定的。好,我们来修改一下段的大小看看:! I+ S. W" p$ j/ m& C
5.1 连接选项中有一个是/opt:nowin98,意思是将段的大小设定成为Win2000适应 n8 A) j: a: s' T! J; A
的。编译看看:哇塞,变成了2,560byte。看来这个选项确实把文件变小了N多。: v8 Y6 }9 t8 N, Y1 B" |; f- W0 K
5.2 在查察连接选项中还有没有什么特别的。发现/align:xx还可以将段大小缩
' b3 _5 G3 g7 Z: M( ?- a* J小。通过UltraEdit察看刚才/opt:nowin98编译出来的文件,发现每个段的大小都
4 ?* s; b& j. |, o6 O/ L5 h$ D/ L是4K的整数倍。看来/align:xx还有减小的趋势。试一把再说:添加连接选项:
3 |$ K& o1 K: I* A- E/align:16(这个大小已经是能够设定的最小的了)。看看结果:1,408Bytes。厉
( j" E4 ^% A) h% Z1 z* m- }+ K% z害,现在代码更小了。2 B% k% d7 O6 O U
5.3 现在回想起来,执行文件大小有数据段,执行代码段等等,如果把这些段都合
1 \8 j f7 M- u0 N( r. A2 W2 \9 X3 G并起来,是不是就会把段之间的冗余有减小了呢?再试试看:添加选项:
$ X( d1 h. @5 w- L/merge:.data=.text /merge:.rdata=.text。再看看文件大小:1,328bytes。真的
4 d0 C) N5 ^3 h% |1 G很不错了。0 G; \% m+ h% w2 n7 h5 K
: d6 Z5 a( m2 u; {9 L; T7 h) p6、刚才的设定确实不错,似乎达到了我们想要的极限了。但是回头想一下,如果
& A+ b3 a! a7 N! R没有CRT库的话,会不会更小了?实际上确实这样。添加连接选项: /entry:
& ~7 b$ F& M7 J) cmain,把入口地址直接指向我们的main函数看看。得到592Bytes。
5 X8 [( }2 w7 J7 H; j& d5 G y3 c2 F
最终我们得到我们最后的大小592Bytes了。我想这也许是我们通过编译器能够编译9 w2 m; N" R$ E
出来的最小的代码了。
) z& z( ~1 h+ f- U/ `- `) S5 m+ G$ p3 B% G# L2 i
结论:% S- Z% \, ]* L/ |" Q8 y
通过上述的步骤,我们了解了如何修改那些编译连接选项来达到执行文件瘦身的目
q5 ?$ u& ]' ]& d的。但是,通常来讲,在我们的Release文件当中,并不需要如此小的执行文件。6 d2 G2 W9 h0 {( S8 @/ N2 j. N. T
如果想达到瘦身的目的,修改为library:MutiThreaded Dll和添加/opt:nowin98已
7 t* }# j. o! Z1 x7 h经是很好的选择了。其他别的选项在编译的时候或多或少的有警告出现,而且,带$ S+ b8 ^) e! j9 X |
有那些编译选项编出来的执行文件也不一定在各个平台上能够适用。; \& r, i' z F. _
9 E) d7 y3 r2 q另外:如果你的执行文件即使通过了这些设定还是比较大的话,也可以通过一些5 x g% T1 `# b7 v4 A
EXE文件压缩工具来进行压缩。比如UPX等等。在此不再细说了。
- l0 J; W* F8 i# E! m) X) q9 m1 R6 |# `9 I) w
以上部分的不足之处,还请多多指正。 |
|