|
|
|
在网上,有好多绿色软件,不仅功能强大,而且软件本身的体积非常小。有的通常
6 I7 M0 h2 i- E0 e& W8 T& }只在几十K左右。那他们是怎么做到把软件做的怎么小的呢?现在我手把手的告诉
+ x& l2 Y0 Y" X6 D0 M你如何通过修改程序的编译选项来瘦身你的执行文件
" {' D0 G% b& T3 P先看一个最典型的程序:
4 n( |( g, }6 t5 Q0 z2 r. a8 R#include<stdio.h>
( D H& r& P' ~% p+ r- j. G, Pint main()
2 ^* |' u3 ]$ r" v( ]{/ }7 M; n" q5 f5 x0 |, O
printf("Hello,World");5 m% T3 w0 {- p0 ~9 a% |! m
return 0;
E' H7 s2 @! Q1 g B5 q' v8 l4 n+ u$ t}+ v6 i3 |* c7 i( M2 h
: M. h2 l: N) M9 r8 s
上面的程序之所以被称之为典型,是因为他有如下的内容:3 D6 q0 O/ h7 N
1、系统函数调用:printf; ]# r: R- @1 g+ G) O) T
2、有静态数据段
+ J- Q2 s# t5 N$ ?9 ?+ N5 {- M7 ^
: Z v0 Y2 d0 R. R. x好,现在把此文件放到VisualStudio6.0中进行编译,看看文件有多大。& b6 y, L% M0 I9 l0 ]7 }
1、用VisualStudio6.0打开HelloWorld.cpp文件,直接按F7。然后点击OK,生成' p! y/ T9 A, E- [$ A0 e; n5 w1 q
Project文件,然后进行编译。编译完成了以后,看看Debug目录下的执行文件的大
+ ]/ q3 ?& X* R5 O9 i( a6 r小,为172,096Bytes。
K& x+ r0 D: V" N1 H: ~0 i- A7 b
/ C" I, g# Y# q2、刚才编译的Debug文件,现在修改成Release文件看看。选择Win32 Release,再
$ h; p4 o6 \& O' S9 Q1 J" m编译。察看执行文件大小,现在成了40,960Bytes。看来Debug版本的要比Release% F, x9 j4 A+ U% Z! n
的小。/ a) Z& g& X. l! I9 u
* s- W, _, C( ]8 G h9 a" a
3、检查代码优化:发现执行文件的优化是Maximize Speed。那么修改成Minimize
; @4 J8 A: E6 j E! ^) }Size看看。重新编译,得到执行文件的大小为:40,960Bytes。看来大小没什么变6 L% ~' w: w: f3 o
化。其实这是由于我们的代码本身太小的缘故,导致即使变化了也看不出来。 l6 M Q' r, y+ y5 a. L4 Q
7 L( F( c M9 N: i
4、想想我们程序的main函数是由CRT类库进行引导的。在我们现在的设定当中,由
# q: d/ [8 W& M, Z M3 S于采取的是系统缺省的编译连接方式(缺省为编译为Single Thread,Static
* i: \; D; N0 Y" tLibrary),所以,在我们的执行文件当中,包含了CRT的二进制代码。好,修改编5 b3 a% @8 M9 {
译选项:C/C++ => Category:Code Generation => Use run-time
8 X% ^+ y) N1 }7 W8 clibrary:MutiThreaded Dll。编译看看:执行文件大小变成了16,384Bytes。
t. v5 v6 b6 L1 ^# q) w4 c; A, L& y' t$ x$ L
5、刚才的设定确实不错,一下子把执行文件大小减小到了16K。现在用UltraEdit
9 r9 ?" e3 U+ g5 C: `9 L看看执行文件都是些什么内容。结果大吃一惊:基本上都是0。看来这个有减小的, |; ?7 F" Z. i" y' m0 D
必要了。都知道,执行文件都有自己的代码段,数据段等等,每个段的大小也是采
* e. X: w3 x9 ]2 V用编译器缺省设定的。好,我们来修改一下段的大小看看:( a& z! w9 B* u. ~% @% r% O8 W
5.1 连接选项中有一个是/opt:nowin98,意思是将段的大小设定成为Win2000适应9 Y; j8 M i' Q
的。编译看看:哇塞,变成了2,560byte。看来这个选项确实把文件变小了N多。
1 o2 ^4 S7 k" h5.2 在查察连接选项中还有没有什么特别的。发现/align:xx还可以将段大小缩) {( P9 v# c- {$ I" |6 B# b
小。通过UltraEdit察看刚才/opt:nowin98编译出来的文件,发现每个段的大小都
3 p7 w( N, [% ^6 @) {是4K的整数倍。看来/align:xx还有减小的趋势。试一把再说:添加连接选项:7 J$ i2 h- M# v' {! [' ~ C- }6 Z
/align:16(这个大小已经是能够设定的最小的了)。看看结果:1,408Bytes。厉
" w) T. L+ K2 R- d5 e害,现在代码更小了。4 z& ^9 x/ \( T h- s! j' T
5.3 现在回想起来,执行文件大小有数据段,执行代码段等等,如果把这些段都合0 ^4 u0 j! x$ X2 O) y
并起来,是不是就会把段之间的冗余有减小了呢?再试试看:添加选项:4 q: H' `3 J, Y& s+ B7 A
/merge:.data=.text /merge:.rdata=.text。再看看文件大小:1,328bytes。真的- P. `& @3 q5 _: ?) D+ h
很不错了。
" W! j c9 S7 W1 u! @ L- u+ E+ T# ?4 ^! G8 p# `
6、刚才的设定确实不错,似乎达到了我们想要的极限了。但是回头想一下,如果0 O$ a4 @) P K: D; `0 l) H, l# r
没有CRT库的话,会不会更小了?实际上确实这样。添加连接选项: /entry:' f; W7 B7 a9 W
main,把入口地址直接指向我们的main函数看看。得到592Bytes。
4 ^3 q9 h5 I U
6 V2 q6 H; D: W+ d, o! X& R6 i( n/ f最终我们得到我们最后的大小592Bytes了。我想这也许是我们通过编译器能够编译
2 L) I7 i1 Z' G1 v& q出来的最小的代码了。
2 f! Z, {, p, \. _- S
' f- [5 x% { F: r+ Y) Y结论:
' k" N! Y5 D W0 D( c通过上述的步骤,我们了解了如何修改那些编译连接选项来达到执行文件瘦身的目
5 u5 g6 R0 g! O6 v的。但是,通常来讲,在我们的Release文件当中,并不需要如此小的执行文件。! N1 N1 F% k7 Z! K8 P
如果想达到瘦身的目的,修改为library:MutiThreaded Dll和添加/opt:nowin98已
; T1 N* r! ]% x. l2 {经是很好的选择了。其他别的选项在编译的时候或多或少的有警告出现,而且,带1 U a' l; x# I4 T0 c; s
有那些编译选项编出来的执行文件也不一定在各个平台上能够适用。& X) p2 M+ O; N) N$ _( Y
4 H0 v+ h- K9 F! b% V+ v) P
另外:如果你的执行文件即使通过了这些设定还是比较大的话,也可以通过一些
# [: w; x' S* Z6 {& sEXE文件压缩工具来进行压缩。比如UPX等等。在此不再细说了。1 \" [- b/ m/ f
* Q# n6 t* l0 `$ c0 V
以上部分的不足之处,还请多多指正。 |
|