|
|
|
在网上,有好多绿色软件,不仅功能强大,而且软件本身的体积非常小。有的通常5 v( U. e& R& y0 ?6 C0 h
只在几十K左右。那他们是怎么做到把软件做的怎么小的呢?现在我手把手的告诉7 a# g& ^. u) B7 i
你如何通过修改程序的编译选项来瘦身你的执行文件
! o' m$ {1 G& s# d* R先看一个最典型的程序:
& A1 B D5 l- V+ `0 B% T8 R#include<stdio.h>) F3 O6 e6 q& H
int main()3 I! `8 \/ N' G; J7 s6 H; s* M
{1 r5 C2 }0 p( m8 L" x
printf("Hello,World");
! ~- ^* b; t0 Z' `& x9 _5 B return 0;0 ?7 |( ^. E( T8 g: i
}5 |. O3 B3 k% }7 `& Y1 G
0 Q+ w) s2 ]" a6 R: `% T0 G6 }上面的程序之所以被称之为典型,是因为他有如下的内容:. h" v! x4 n, W5 s3 ?
1、系统函数调用:printf
& i5 [$ p- Q8 D2 ^: n2、有静态数据段
1 z! Q* a8 ?* F
) I3 z5 V7 ^+ u& X: z F3 \7 T' ~" `好,现在把此文件放到VisualStudio6.0中进行编译,看看文件有多大。$ j# ^- q8 A4 Z7 \ J* \1 Q! w* I
1、用VisualStudio6.0打开HelloWorld.cpp文件,直接按F7。然后点击OK,生成1 Y; O5 k/ g# T0 _: {/ d5 u: D
Project文件,然后进行编译。编译完成了以后,看看Debug目录下的执行文件的大; ?$ D* H1 `! \( w: w# Z
小,为172,096Bytes。1 ^0 c o# ]& X) z! }( p, g
$ l0 l6 v9 R |4 N2、刚才编译的Debug文件,现在修改成Release文件看看。选择Win32 Release,再9 q# Z. \' A% o1 J! H
编译。察看执行文件大小,现在成了40,960Bytes。看来Debug版本的要比Release
. `# d( @4 x+ K' J! w) V8 \! t的小。% U, r% O. X/ j# J j6 e$ O( k# R# c
7 X) {' f$ d! {! G; C3、检查代码优化:发现执行文件的优化是Maximize Speed。那么修改成Minimize
8 S3 T3 a8 {* L5 W, e) HSize看看。重新编译,得到执行文件的大小为:40,960Bytes。看来大小没什么变. Y6 \- Z5 S l
化。其实这是由于我们的代码本身太小的缘故,导致即使变化了也看不出来。0 w7 n5 T, v) {0 s, h
- H# U9 C8 Q' Y7 Q8 t! F, X
4、想想我们程序的main函数是由CRT类库进行引导的。在我们现在的设定当中,由# |! n7 c5 y, {+ L4 g/ ^! A0 R
于采取的是系统缺省的编译连接方式(缺省为编译为Single Thread,Static
) F* s# ^3 h! ALibrary),所以,在我们的执行文件当中,包含了CRT的二进制代码。好,修改编
+ z0 V5 v' o' J: u译选项:C/C++ => Category:Code Generation => Use run-time. t2 y4 L- K! {3 O* I
library:MutiThreaded Dll。编译看看:执行文件大小变成了16,384Bytes。* Q$ x& O' H# @! s i
/ [# u3 G% E: r, N+ f
5、刚才的设定确实不错,一下子把执行文件大小减小到了16K。现在用UltraEdit
& a8 l( I3 ]3 p' T9 h+ x/ [看看执行文件都是些什么内容。结果大吃一惊:基本上都是0。看来这个有减小的; ` A( m3 |/ ?5 ] @4 E) c
必要了。都知道,执行文件都有自己的代码段,数据段等等,每个段的大小也是采
; \9 d( n {" `" o$ V, K ]用编译器缺省设定的。好,我们来修改一下段的大小看看:! U8 o; b5 h% u$ _/ }; k
5.1 连接选项中有一个是/opt:nowin98,意思是将段的大小设定成为Win2000适应
. h$ ^4 T0 R6 d% i7 Y( `的。编译看看:哇塞,变成了2,560byte。看来这个选项确实把文件变小了N多。- C" ]% z, D! h- `/ u, j8 g' U7 e
5.2 在查察连接选项中还有没有什么特别的。发现/align:xx还可以将段大小缩
; w1 K( F2 B9 p& _) W0 ~2 V3 X; V小。通过UltraEdit察看刚才/opt:nowin98编译出来的文件,发现每个段的大小都1 ]9 V) v5 [+ E4 V; r; y, u
是4K的整数倍。看来/align:xx还有减小的趋势。试一把再说:添加连接选项:
" w# B+ O# [; A5 Z* s1 X* W/align:16(这个大小已经是能够设定的最小的了)。看看结果:1,408Bytes。厉
6 K! c0 [/ l6 ]9 V+ ~& e3 S8 w害,现在代码更小了。
3 M& Y: t4 L+ C$ M5 s. _, M; }5.3 现在回想起来,执行文件大小有数据段,执行代码段等等,如果把这些段都合8 f. K) \' i% F% m" j6 m) a
并起来,是不是就会把段之间的冗余有减小了呢?再试试看:添加选项:
- s; ~4 |& N6 V) x2 e/merge:.data=.text /merge:.rdata=.text。再看看文件大小:1,328bytes。真的6 f. b& O0 p8 v
很不错了。; H+ G* X ]3 g! o3 S P% G
, ^% w5 Y5 B% Y. W! ] t
6、刚才的设定确实不错,似乎达到了我们想要的极限了。但是回头想一下,如果$ c: [! }6 ~8 H8 o
没有CRT库的话,会不会更小了?实际上确实这样。添加连接选项: /entry:) o# Z4 y* C' ?* i
main,把入口地址直接指向我们的main函数看看。得到592Bytes。3 @' E w* `% q" l& g
+ b: r0 b+ N) M* Q8 U
最终我们得到我们最后的大小592Bytes了。我想这也许是我们通过编译器能够编译3 I0 F' e5 k) b
出来的最小的代码了。. J" B2 A# \5 j, a7 Y' K
! E3 ?' b J3 C% m7 x2 L
结论:
$ E; \9 [4 H5 _8 y8 {2 r1 [/ c通过上述的步骤,我们了解了如何修改那些编译连接选项来达到执行文件瘦身的目
! e* V" q0 }3 {2 f* W2 e' h% V的。但是,通常来讲,在我们的Release文件当中,并不需要如此小的执行文件。1 L8 Y* F+ v5 i$ e
如果想达到瘦身的目的,修改为library:MutiThreaded Dll和添加/opt:nowin98已' h7 q. v o6 w9 {- M, J8 p
经是很好的选择了。其他别的选项在编译的时候或多或少的有警告出现,而且,带
/ M. _/ T0 a$ X9 v; f' h$ Q有那些编译选项编出来的执行文件也不一定在各个平台上能够适用。
5 O% m3 s2 y" w1 e' H. k5 ?9 f) D4 b+ }. H. E# k" v d! i
另外:如果你的执行文件即使通过了这些设定还是比较大的话,也可以通过一些3 l% X; Y! H$ H% ]! C9 i/ H
EXE文件压缩工具来进行压缩。比如UPX等等。在此不再细说了。
, S5 d) y; m: r2 {, T1 h, m
3 U8 B% a- s% T: T以上部分的不足之处,还请多多指正。 |
|