|
在网上,有好多绿色软件,不仅功能强大,而且软件本身的体积非常小。有的通常8 a9 W: I5 ]) u9 z+ c
只在几十K左右。那他们是怎么做到把软件做的怎么小的呢?现在我手把手的告诉
8 g+ Y4 [# y9 _" K你如何通过修改程序的编译选项来瘦身你的执行文件
; [$ ~. ?' @8 h2 i: I先看一个最典型的程序: 8 r1 M& M3 q H8 n8 u, R Y
#include<stdio.h>1 x3 l3 |/ }; G* w; Y
int main()
( ~6 e' X1 w$ @& u{
; J E* r" e& Q% V2 K! \ printf("Hello,World");$ ?1 d) e& I0 L* Z
return 0;
6 f: v/ T& D& ~, h- H( M8 P7 u}
7 y$ u" u# _+ ~0 g% k; D: H
3 a+ L3 Y. _& g4 Z3 i; @& \上面的程序之所以被称之为典型,是因为他有如下的内容:! [1 s+ I( C3 D3 G: B0 F
1、系统函数调用:printf
( v! o& J' R( Q' a7 p* ]2、有静态数据段
2 w3 ?, a5 D$ q% M2 ^+ N; n8 A+ c: c: T2 X; D& X' r7 h
好,现在把此文件放到VisualStudio6.0中进行编译,看看文件有多大。0 m" M) o& k1 A9 s" q
1、用VisualStudio6.0打开HelloWorld.cpp文件,直接按F7。然后点击OK,生成
+ Z9 j; W' m. U; i9 E+ J6 fProject文件,然后进行编译。编译完成了以后,看看Debug目录下的执行文件的大
5 }) h6 Q4 y& P5 m; N9 C2 s1 k+ Z' d1 X小,为172,096Bytes。9 D. B! }! m( d( }
" I; r' ?# R: f1 e8 h2、刚才编译的Debug文件,现在修改成Release文件看看。选择Win32 Release,再& ?- W$ h$ {, c
编译。察看执行文件大小,现在成了40,960Bytes。看来Debug版本的要比Release
' f, [7 c. d7 ?* A9 d% Y的小。1 v0 L& i- b! \0 m2 r6 H. B1 M; M
; _ }5 S4 |7 V. e% `, B# c
3、检查代码优化:发现执行文件的优化是Maximize Speed。那么修改成Minimize
% w3 R: u: l6 ~; v* T( BSize看看。重新编译,得到执行文件的大小为:40,960Bytes。看来大小没什么变
o2 X4 M8 a* q4 x1 }化。其实这是由于我们的代码本身太小的缘故,导致即使变化了也看不出来。
2 S! j6 t6 k1 n) l3 m$ s) ~3 B& M8 D; H0 S+ R+ U" M
4、想想我们程序的main函数是由CRT类库进行引导的。在我们现在的设定当中,由
. C% J4 Z# J) F L于采取的是系统缺省的编译连接方式(缺省为编译为Single Thread,Static
7 Y% `( z0 G1 Q& {6 T$ k8 ELibrary),所以,在我们的执行文件当中,包含了CRT的二进制代码。好,修改编* ~- a4 Z% q5 A4 I
译选项:C/C++ => Category:Code Generation => Use run-time
! g2 G0 w8 M; `: tlibrary:MutiThreaded Dll。编译看看:执行文件大小变成了16,384Bytes。- g. B5 V# ?" T0 j9 a# }. M
$ U* c' M0 _% B2 z4 }6 e5、刚才的设定确实不错,一下子把执行文件大小减小到了16K。现在用UltraEdit
6 q' H% a5 @$ F# Y2 H* V看看执行文件都是些什么内容。结果大吃一惊:基本上都是0。看来这个有减小的
+ n- m9 r/ @& I* A v1 r0 m必要了。都知道,执行文件都有自己的代码段,数据段等等,每个段的大小也是采* G; T3 P- g% U+ [9 c3 l/ J
用编译器缺省设定的。好,我们来修改一下段的大小看看:: T7 e' t1 a( D
5.1 连接选项中有一个是/opt:nowin98,意思是将段的大小设定成为Win2000适应0 D9 x7 {/ K: z' D) K& z- p" F
的。编译看看:哇塞,变成了2,560byte。看来这个选项确实把文件变小了N多。2 E9 C* P& m, V0 c
5.2 在查察连接选项中还有没有什么特别的。发现/align:xx还可以将段大小缩
4 A' o2 v1 M, |- s小。通过UltraEdit察看刚才/opt:nowin98编译出来的文件,发现每个段的大小都+ J7 t) D3 v% Y, A: T/ K
是4K的整数倍。看来/align:xx还有减小的趋势。试一把再说:添加连接选项:
: A1 U! k$ H! A0 g# u/ }/align:16(这个大小已经是能够设定的最小的了)。看看结果:1,408Bytes。厉( M9 y' b$ F6 q' _5 G
害,现在代码更小了。+ }% i* Y4 |/ G2 l+ H3 }0 n5 L t0 j
5.3 现在回想起来,执行文件大小有数据段,执行代码段等等,如果把这些段都合
: R! O2 i* i, \6 h2 l6 Q3 p并起来,是不是就会把段之间的冗余有减小了呢?再试试看:添加选项:
) @& y k5 `; a, U8 k/merge:.data=.text /merge:.rdata=.text。再看看文件大小:1,328bytes。真的 p! K6 w/ ^% ]! `& V! s$ e
很不错了。1 h- t$ S3 }& a% o: _: b, u
: }+ j4 q7 c/ [0 s
6、刚才的设定确实不错,似乎达到了我们想要的极限了。但是回头想一下,如果1 t; l9 A& x$ f! M" m7 A
没有CRT库的话,会不会更小了?实际上确实这样。添加连接选项: /entry:; B8 b' V7 n0 y4 m5 {9 @+ B
main,把入口地址直接指向我们的main函数看看。得到592Bytes。. I/ [% a! v. H$ X5 m8 d8 ]: F
6 W! p- J" ]+ u1 E( x2 l最终我们得到我们最后的大小592Bytes了。我想这也许是我们通过编译器能够编译* L& L, S+ L# D0 b! O1 N! O) ^
出来的最小的代码了。
, l4 M; e% l( B6 ^
8 `. ^* L8 X3 u! Z4 ?结论:) c7 ?2 e& `) R, X
通过上述的步骤,我们了解了如何修改那些编译连接选项来达到执行文件瘦身的目0 N/ Y2 w; ]* Q8 j5 ?" ^ C
的。但是,通常来讲,在我们的Release文件当中,并不需要如此小的执行文件。3 v$ [& }0 q& Q: t2 j3 W
如果想达到瘦身的目的,修改为library:MutiThreaded Dll和添加/opt:nowin98已
3 U- V. |9 i6 a1 B. \经是很好的选择了。其他别的选项在编译的时候或多或少的有警告出现,而且,带
; n8 [4 S0 c' u% m- r有那些编译选项编出来的执行文件也不一定在各个平台上能够适用。: _, V% B( H: s2 @# b) o
; i& C& Q2 h1 o; P另外:如果你的执行文件即使通过了这些设定还是比较大的话,也可以通过一些
& \4 H' ^2 d+ K7 e5 V1 d6 uEXE文件压缩工具来进行压缩。比如UPX等等。在此不再细说了。
6 \* t% E# m5 l! ?( R+ }+ T2 y3 S8 t0 v( i% S
以上部分的不足之处,还请多多指正。 |
|