|
在网上,有好多绿色软件,不仅功能强大,而且软件本身的体积非常小。有的通常
! m2 R9 z5 J7 f: V! k只在几十K左右。那他们是怎么做到把软件做的怎么小的呢?现在我手把手的告诉/ V& v9 B& E) y3 f
你如何通过修改程序的编译选项来瘦身你的执行文件$ c1 G+ U4 v7 I" u/ T7 u7 ~. B
先看一个最典型的程序: % C9 N+ K& P2 E/ I/ n- L: s* K
#include<stdio.h>
) R2 J5 }4 }; s6 N& oint main()3 v4 U. h7 Z# a* v+ g+ R
{8 i) g0 M/ S0 {2 F
printf("Hello,World");. a7 E9 L/ S" g0 ?1 ^+ u
return 0;- G6 f5 L9 m! F* V% F) p! P# z% G
}
1 G* m X* O) g% R" r! d
: ]! G2 V" a9 |4 Q" \上面的程序之所以被称之为典型,是因为他有如下的内容:, t9 n# i/ V# q0 t8 w
1、系统函数调用:printf( J% {% m; L' K: e2 C- D
2、有静态数据段
6 d6 k! i1 i: {. ?# g
4 t- F: e' z- k! C7 O' e# j好,现在把此文件放到VisualStudio6.0中进行编译,看看文件有多大。
. M7 I, [# }5 L1、用VisualStudio6.0打开HelloWorld.cpp文件,直接按F7。然后点击OK,生成" m# T. K* h# ]6 ?5 B- Z ~3 j
Project文件,然后进行编译。编译完成了以后,看看Debug目录下的执行文件的大3 ]; y" [! T% H. ~( F; v
小,为172,096Bytes。
- g8 E7 B+ {8 Z0 c# v1 x+ L. n, Z' L+ J! ]5 S
2、刚才编译的Debug文件,现在修改成Release文件看看。选择Win32 Release,再; x' i/ O5 U# G: l- U8 H
编译。察看执行文件大小,现在成了40,960Bytes。看来Debug版本的要比Release5 m+ W( d5 l$ J1 w5 r
的小。7 Y: c, L+ x4 {: q6 f' o! ^9 @
( O# f/ d* {0 t' r
3、检查代码优化:发现执行文件的优化是Maximize Speed。那么修改成Minimize
! c" n* X2 j$ I/ S( F* a0 PSize看看。重新编译,得到执行文件的大小为:40,960Bytes。看来大小没什么变
- `2 r8 c9 ~( |8 E' F+ z6 m, j化。其实这是由于我们的代码本身太小的缘故,导致即使变化了也看不出来。8 f+ K* M3 |5 ?
* l* D: I* _0 g' ?/ Z
4、想想我们程序的main函数是由CRT类库进行引导的。在我们现在的设定当中,由
% |7 c! A+ j4 v% M7 y于采取的是系统缺省的编译连接方式(缺省为编译为Single Thread,Static. U4 d# q- J* V8 h; U/ D
Library),所以,在我们的执行文件当中,包含了CRT的二进制代码。好,修改编9 w3 {8 F. s Y! C2 W0 E6 i
译选项:C/C++ => Category:Code Generation => Use run-time7 O+ t. w& E9 _
library:MutiThreaded Dll。编译看看:执行文件大小变成了16,384Bytes。: m/ `% y6 u) a6 w7 Z8 k# T, n
7 p" D0 {- D3 k5、刚才的设定确实不错,一下子把执行文件大小减小到了16K。现在用UltraEdit
& F* t4 q# k2 r# ^看看执行文件都是些什么内容。结果大吃一惊:基本上都是0。看来这个有减小的* L" ~2 O; `/ O( q
必要了。都知道,执行文件都有自己的代码段,数据段等等,每个段的大小也是采0 A6 C+ o+ }) |5 a4 D' K1 T
用编译器缺省设定的。好,我们来修改一下段的大小看看:: ~2 |- z# d3 w! @
5.1 连接选项中有一个是/opt:nowin98,意思是将段的大小设定成为Win2000适应0 H5 H5 C3 i2 U# A) v! A
的。编译看看:哇塞,变成了2,560byte。看来这个选项确实把文件变小了N多。
- t7 K4 ?# c P4 o5 g5.2 在查察连接选项中还有没有什么特别的。发现/align:xx还可以将段大小缩( e8 J h. `, O. s" p+ f2 ]' |
小。通过UltraEdit察看刚才/opt:nowin98编译出来的文件,发现每个段的大小都# V% G/ E9 e6 o
是4K的整数倍。看来/align:xx还有减小的趋势。试一把再说:添加连接选项:
+ @( _' U B; }( ?/align:16(这个大小已经是能够设定的最小的了)。看看结果:1,408Bytes。厉# @" N5 D/ j2 _3 w
害,现在代码更小了。" Y! ?5 R4 K6 D4 t! m
5.3 现在回想起来,执行文件大小有数据段,执行代码段等等,如果把这些段都合
8 L4 V7 S7 [/ S6 i" j: R# J并起来,是不是就会把段之间的冗余有减小了呢?再试试看:添加选项:
* A4 D( O4 b9 y- t/ i# W/merge:.data=.text /merge:.rdata=.text。再看看文件大小:1,328bytes。真的 a5 u* ?5 H' P5 G, J
很不错了。% O3 A s4 ]9 x" |, K
5 ^9 R* L7 ~6 U
6、刚才的设定确实不错,似乎达到了我们想要的极限了。但是回头想一下,如果7 k- ^/ {) i/ \% U
没有CRT库的话,会不会更小了?实际上确实这样。添加连接选项: /entry:
/ }% U1 q# Q. E8 Nmain,把入口地址直接指向我们的main函数看看。得到592Bytes。
9 A1 x r4 ~% L' J+ }6 A( i8 o p. C0 J f8 H
最终我们得到我们最后的大小592Bytes了。我想这也许是我们通过编译器能够编译+ {. Y- j8 k, q
出来的最小的代码了。( A- y/ z; {4 e3 j
( C0 `; q. x: H; a& b7 f结论:* e- U$ j: `# H9 w: v/ z$ A
通过上述的步骤,我们了解了如何修改那些编译连接选项来达到执行文件瘦身的目
% T$ b7 C2 \; f的。但是,通常来讲,在我们的Release文件当中,并不需要如此小的执行文件。; m7 z/ ?( B4 M5 Z
如果想达到瘦身的目的,修改为library:MutiThreaded Dll和添加/opt:nowin98已8 S, Z0 Y" ^7 @9 A
经是很好的选择了。其他别的选项在编译的时候或多或少的有警告出现,而且,带
% n+ p1 {. A. H+ A) s, v有那些编译选项编出来的执行文件也不一定在各个平台上能够适用。
8 Z& ? i9 M4 Y. s- t& o& ]6 n0 C0 m$ |: b# h' f
另外:如果你的执行文件即使通过了这些设定还是比较大的话,也可以通过一些4 @ \/ R, i* D
EXE文件压缩工具来进行压缩。比如UPX等等。在此不再细说了。
; y# x- ]1 l9 K" h4 d8 s$ }4 ^8 ]/ ]! K
以上部分的不足之处,还请多多指正。 |
|