|
|
|
在网上,有好多绿色软件,不仅功能强大,而且软件本身的体积非常小。有的通常
' D X% Q! x3 [+ h1 |& R2 c只在几十K左右。那他们是怎么做到把软件做的怎么小的呢?现在我手把手的告诉4 V: E5 k; O) l7 d
你如何通过修改程序的编译选项来瘦身你的执行文件" T) v2 g2 {- V7 k8 F6 G; z
先看一个最典型的程序: , a, ]0 i/ L( D
#include<stdio.h>
3 D; @- v; j6 A6 v/ e! Jint main()
" C$ s" M2 s4 Y$ U{
$ I# W# O& o: v printf("Hello,World");) S8 c& Z2 n1 O0 g- Z2 S8 ?1 x
return 0;, S6 X( a/ A5 ?
}' ~- K% N+ ~2 [# w+ ?( `
p: e; t4 d$ g8 w/ [) M7 r上面的程序之所以被称之为典型,是因为他有如下的内容:
( L) \+ L; w8 ] L/ ]# g6 y% T1、系统函数调用:printf6 Q* C& L' [5 f1 k% W3 @
2、有静态数据段' m _0 s8 f) }2 ]
7 s7 K2 ?8 a+ G0 D! L" M好,现在把此文件放到VisualStudio6.0中进行编译,看看文件有多大。8 s- S" }( d0 R, M0 A
1、用VisualStudio6.0打开HelloWorld.cpp文件,直接按F7。然后点击OK,生成
: @$ Z5 H! H# r1 m1 R% _Project文件,然后进行编译。编译完成了以后,看看Debug目录下的执行文件的大: R$ Y, l% X- s; c8 h. c
小,为172,096Bytes。: v9 U3 y( B, m, s
3 r; |) w, e3 i5 i8 {2、刚才编译的Debug文件,现在修改成Release文件看看。选择Win32 Release,再/ t$ k+ j: a: X& f) G7 [, @
编译。察看执行文件大小,现在成了40,960Bytes。看来Debug版本的要比Release0 h4 r! A* G2 h. A
的小。
6 u/ [+ [/ @' ]' b- }4 c0 d1 D" D/ H$ i
3、检查代码优化:发现执行文件的优化是Maximize Speed。那么修改成Minimize
6 B* m+ E; W3 t1 m& p6 SSize看看。重新编译,得到执行文件的大小为:40,960Bytes。看来大小没什么变0 c4 y' s3 @% W, ]+ B
化。其实这是由于我们的代码本身太小的缘故,导致即使变化了也看不出来。% s" Y: d; ]9 m. J
% Z! D. A( i% E4 M7 J7 L
4、想想我们程序的main函数是由CRT类库进行引导的。在我们现在的设定当中,由0 l; r5 Z4 m0 w: Z# c. ~0 k% a
于采取的是系统缺省的编译连接方式(缺省为编译为Single Thread,Static) K5 _2 I8 Q, [$ j @
Library),所以,在我们的执行文件当中,包含了CRT的二进制代码。好,修改编
: _! {- B4 y4 r/ `5 i译选项:C/C++ => Category:Code Generation => Use run-time
7 p. l8 A( y# z7 D K' x7 `library:MutiThreaded Dll。编译看看:执行文件大小变成了16,384Bytes。
5 z: H9 H& b; \7 F, g& y0 s% r, m9 Z! m9 Y
5、刚才的设定确实不错,一下子把执行文件大小减小到了16K。现在用UltraEdit
6 M0 e- x6 U! l5 K! ~+ ^看看执行文件都是些什么内容。结果大吃一惊:基本上都是0。看来这个有减小的! ?. F. U$ T; f( e' `5 M
必要了。都知道,执行文件都有自己的代码段,数据段等等,每个段的大小也是采0 s/ g$ b6 r* U9 c- O9 o( `
用编译器缺省设定的。好,我们来修改一下段的大小看看:
, B t2 G' Q( n* Z2 g5.1 连接选项中有一个是/opt:nowin98,意思是将段的大小设定成为Win2000适应% ~. o8 B* E3 H" p9 n& I
的。编译看看:哇塞,变成了2,560byte。看来这个选项确实把文件变小了N多。7 Z: e6 a: S. O3 P: j" k
5.2 在查察连接选项中还有没有什么特别的。发现/align:xx还可以将段大小缩- A4 O: x8 M8 `0 X* n
小。通过UltraEdit察看刚才/opt:nowin98编译出来的文件,发现每个段的大小都7 G* s& r# h. L; U2 P# B
是4K的整数倍。看来/align:xx还有减小的趋势。试一把再说:添加连接选项:1 v) o; H. L( E' p
/align:16(这个大小已经是能够设定的最小的了)。看看结果:1,408Bytes。厉# d- N5 R1 ?( G, h! |; `; w6 K
害,现在代码更小了。' {3 n3 ~9 Z$ S& y5 B8 C" Y: }
5.3 现在回想起来,执行文件大小有数据段,执行代码段等等,如果把这些段都合
* B3 [7 A$ _/ |8 ~% x并起来,是不是就会把段之间的冗余有减小了呢?再试试看:添加选项:1 U J& n/ R0 a1 j
/merge:.data=.text /merge:.rdata=.text。再看看文件大小:1,328bytes。真的
: M2 ^- b0 n) K1 l& q# t3 F# O3 q很不错了。
( m9 S! o# l( K: |) ?# }* \6 @- z$ Q- Z4 j
6、刚才的设定确实不错,似乎达到了我们想要的极限了。但是回头想一下,如果
2 ?, e* v* K0 z+ ?' v% i没有CRT库的话,会不会更小了?实际上确实这样。添加连接选项: /entry:
. X$ n. M. i9 V' s+ a/ _main,把入口地址直接指向我们的main函数看看。得到592Bytes。6 K2 Z9 @* j) o3 v, T2 e% P
" v4 Y: @' ^. v# `
最终我们得到我们最后的大小592Bytes了。我想这也许是我们通过编译器能够编译
; c" v) l; J' A* D; S% X; O8 o出来的最小的代码了。
: ?( Q4 I/ s9 @* B0 G1 O6 Q& U8 y( f( d2 T3 b; N2 M: |2 Y
结论:
( W8 [* ^1 P% J# L* L# ^通过上述的步骤,我们了解了如何修改那些编译连接选项来达到执行文件瘦身的目6 A$ o9 Y8 u, z5 x/ b
的。但是,通常来讲,在我们的Release文件当中,并不需要如此小的执行文件。; D( d" ?( q0 A* \2 q* e) l
如果想达到瘦身的目的,修改为library:MutiThreaded Dll和添加/opt:nowin98已
8 `# H8 w, J' B9 \8 V2 _$ ?0 d, l经是很好的选择了。其他别的选项在编译的时候或多或少的有警告出现,而且,带
' C+ \/ _: m1 q, M1 I2 \6 l- b有那些编译选项编出来的执行文件也不一定在各个平台上能够适用。
; P9 x; m8 `2 ^. W
' z- b- z, T+ h& J" R- d4 f另外:如果你的执行文件即使通过了这些设定还是比较大的话,也可以通过一些/ t {% U+ V* ?
EXE文件压缩工具来进行压缩。比如UPX等等。在此不再细说了。
$ n5 {; [$ }! w3 j% Q: |+ }0 k$ h f( h( ^2 w
以上部分的不足之处,还请多多指正。 |
|