|
|
|
在网上,有好多绿色软件,不仅功能强大,而且软件本身的体积非常小。有的通常4 ?: ?+ j7 ?7 r, t. Y& e
只在几十K左右。那他们是怎么做到把软件做的怎么小的呢?现在我手把手的告诉6 C/ Y) p" |! Y5 j& M1 ~7 Q
你如何通过修改程序的编译选项来瘦身你的执行文件
5 u6 w: N- p- L$ P w3 V先看一个最典型的程序: 1 l0 I' U% H1 Y+ x2 k" T( W
#include<stdio.h>
9 {8 c$ `, Y+ r' z9 e* Mint main()5 q q: i' ]7 E( T4 v, v
{
7 v2 S6 j0 A- w- x' g2 r7 q# `( X printf("Hello,World");% ~% b% p! m( B! n
return 0;; E5 v$ d! t: L4 g! x( Y
}
* U: `. @6 d$ w0 k4 ~, J Q5 @2 a* G1 c* v( e: B. Q5 A
上面的程序之所以被称之为典型,是因为他有如下的内容:# |8 ?8 M; A. }1 E3 U) W; B/ O
1、系统函数调用:printf
0 D6 W9 T# u% H4 `; m W7 N P2、有静态数据段' o: j% S( ~3 i1 _
8 c0 T; F) s; N1 `; T P9 r
好,现在把此文件放到VisualStudio6.0中进行编译,看看文件有多大。: V$ A% s, m) x$ ^, f- N' x; m
1、用VisualStudio6.0打开HelloWorld.cpp文件,直接按F7。然后点击OK,生成6 u- f) m6 n9 m! M/ X2 x7 m9 ?) |% z
Project文件,然后进行编译。编译完成了以后,看看Debug目录下的执行文件的大
5 Y4 o# g+ p2 l! r& W4 C小,为172,096Bytes。; ?1 q2 E0 F2 q, o6 F
7 `6 v( O! n6 w+ _& p( Z1 x
2、刚才编译的Debug文件,现在修改成Release文件看看。选择Win32 Release,再
* L( ?& O8 a L) \编译。察看执行文件大小,现在成了40,960Bytes。看来Debug版本的要比Release
, y0 F7 g( |* E2 L; I# g9 c# Y的小。" q' k/ _ G: K- w+ _! t
" ? M f4 m7 K( k+ q! G
3、检查代码优化:发现执行文件的优化是Maximize Speed。那么修改成Minimize
0 m$ n& P- k! o/ R' }Size看看。重新编译,得到执行文件的大小为:40,960Bytes。看来大小没什么变7 C4 ~4 C. O5 _& D
化。其实这是由于我们的代码本身太小的缘故,导致即使变化了也看不出来。9 A- o( |/ B, X7 i4 N0 p7 f- y
& [; V7 B( q# R3 w3 t
4、想想我们程序的main函数是由CRT类库进行引导的。在我们现在的设定当中,由* c! ?/ i+ y o6 |8 \) J
于采取的是系统缺省的编译连接方式(缺省为编译为Single Thread,Static
8 n' _ u7 |# ]9 }2 `, U0 t$ [8 fLibrary),所以,在我们的执行文件当中,包含了CRT的二进制代码。好,修改编
2 E$ A7 o4 @0 O5 L& v译选项:C/C++ => Category:Code Generation => Use run-time5 @1 G2 ^! W) i, l V3 B
library:MutiThreaded Dll。编译看看:执行文件大小变成了16,384Bytes。3 d; g1 @2 F; N2 C8 s
$ H; ]( Y" M9 G! z x
5、刚才的设定确实不错,一下子把执行文件大小减小到了16K。现在用UltraEdit! W; e( o( w3 q' F/ n
看看执行文件都是些什么内容。结果大吃一惊:基本上都是0。看来这个有减小的$ ^) _) R% I5 N- C! C, ?9 Y' z
必要了。都知道,执行文件都有自己的代码段,数据段等等,每个段的大小也是采
' L: ? M1 [$ j$ \3 J- W用编译器缺省设定的。好,我们来修改一下段的大小看看:
5 `/ O3 @- W c/ t+ ~5.1 连接选项中有一个是/opt:nowin98,意思是将段的大小设定成为Win2000适应) S8 r1 S4 O" N7 @+ T; r; w2 L# q+ R- i
的。编译看看:哇塞,变成了2,560byte。看来这个选项确实把文件变小了N多。4 I! p/ y. g! n
5.2 在查察连接选项中还有没有什么特别的。发现/align:xx还可以将段大小缩
4 W. x* L; o B" B! o5 J小。通过UltraEdit察看刚才/opt:nowin98编译出来的文件,发现每个段的大小都
5 v5 G8 O8 `. l9 I$ v' m是4K的整数倍。看来/align:xx还有减小的趋势。试一把再说:添加连接选项:8 N J8 Q& n) T; D
/align:16(这个大小已经是能够设定的最小的了)。看看结果:1,408Bytes。厉& ]6 l5 }9 J5 E9 c9 M, i# u0 L7 b
害,现在代码更小了。9 `) f! S" ^9 V
5.3 现在回想起来,执行文件大小有数据段,执行代码段等等,如果把这些段都合
! M# k9 f b3 R. s4 L* P并起来,是不是就会把段之间的冗余有减小了呢?再试试看:添加选项:; D4 n6 o6 e, x% ^* t/ c. _
/merge:.data=.text /merge:.rdata=.text。再看看文件大小:1,328bytes。真的+ N) h8 y' a6 J+ z
很不错了。
4 t8 q# P: D7 v% N# r2 q) Q W: H" P6 x+ n
6、刚才的设定确实不错,似乎达到了我们想要的极限了。但是回头想一下,如果
: G5 E, m1 y8 W4 i没有CRT库的话,会不会更小了?实际上确实这样。添加连接选项: /entry:" D; Q6 g0 X$ P6 J8 r+ @& d
main,把入口地址直接指向我们的main函数看看。得到592Bytes。
& ~$ F3 I* n6 D( r' ?5 M1 y# u7 h6 W, }0 S0 X% J; c
最终我们得到我们最后的大小592Bytes了。我想这也许是我们通过编译器能够编译7 m6 y2 M, a/ U6 l
出来的最小的代码了。
% F" l$ m- l8 n2 `2 q0 m6 g: n$ E2 a) X0 j6 _' z4 Y# U6 V! |+ d* g
结论:4 _" F* L* a; ^' L9 ~& d. `( {
通过上述的步骤,我们了解了如何修改那些编译连接选项来达到执行文件瘦身的目
: X1 l* t. p# T. Z8 B的。但是,通常来讲,在我们的Release文件当中,并不需要如此小的执行文件。
* [7 T3 r( @% G7 V4 W3 J如果想达到瘦身的目的,修改为library:MutiThreaded Dll和添加/opt:nowin98已
7 Y: h/ V5 A9 k& U经是很好的选择了。其他别的选项在编译的时候或多或少的有警告出现,而且,带+ ^& t" J: x; {4 `1 ^
有那些编译选项编出来的执行文件也不一定在各个平台上能够适用。
/ e$ E& `# B, a, T
. J4 _5 O3 Q, ^: T/ K另外:如果你的执行文件即使通过了这些设定还是比较大的话,也可以通过一些6 f' ]7 M6 x& |& B5 M4 v& t+ E% d
EXE文件压缩工具来进行压缩。比如UPX等等。在此不再细说了。% P4 ^! L. x! q/ `: v" a
/ e9 F: t, t& [, R7 ~; K6 c- @以上部分的不足之处,还请多多指正。 |
|