|
在网上,有好多绿色软件,不仅功能强大,而且软件本身的体积非常小。有的通常
+ @. ~* K5 l; y只在几十K左右。那他们是怎么做到把软件做的怎么小的呢?现在我手把手的告诉4 D" Y0 y; e: M% f0 L- G( H% {4 g
你如何通过修改程序的编译选项来瘦身你的执行文件& ^, {. Q- X8 v- e
先看一个最典型的程序:
* K' k( ~8 A3 Z! @8 H3 q#include<stdio.h>
* N) l( J# o5 |+ B% p) l5 P# zint main()+ n* d; z, C& u2 _0 l
{
o2 X! `3 c( V1 V2 t( Y printf("Hello,World");
2 ]5 O* d5 u' i! R$ M5 f return 0;
. N/ I O1 M" k/ d6 c# ~- t}: \6 M9 ^- U7 s& K
- B0 [' c& G+ T& I* m
上面的程序之所以被称之为典型,是因为他有如下的内容:: Y0 i) h- H3 p( [9 U- {" @
1、系统函数调用:printf
$ |% ]: _* \8 v' r9 J2、有静态数据段+ u- A1 U2 k( b* n+ l" a& ~( W
: f3 q$ l! p8 {# k: y好,现在把此文件放到VisualStudio6.0中进行编译,看看文件有多大。7 |; N' }% N: F
1、用VisualStudio6.0打开HelloWorld.cpp文件,直接按F7。然后点击OK,生成
3 i5 ?1 Q, t+ B4 tProject文件,然后进行编译。编译完成了以后,看看Debug目录下的执行文件的大8 Z) [' L' x+ q' p V* h
小,为172,096Bytes。' V2 ?( k9 }, q0 o' s( U
1 {4 h- n5 v- \3 I2 N7 M( Q
2、刚才编译的Debug文件,现在修改成Release文件看看。选择Win32 Release,再. T1 @+ U3 D5 H! {, A
编译。察看执行文件大小,现在成了40,960Bytes。看来Debug版本的要比Release) k: L3 g6 E+ |, b% Z- K7 N
的小。/ L) p+ \: S* m3 k3 B! i! `
& G* J+ r" @- `% s; d1 d9 D
3、检查代码优化:发现执行文件的优化是Maximize Speed。那么修改成Minimize
" b5 l& t4 }. o1 R, mSize看看。重新编译,得到执行文件的大小为:40,960Bytes。看来大小没什么变
, q7 y* X. i$ u) _1 g化。其实这是由于我们的代码本身太小的缘故,导致即使变化了也看不出来。
r0 G( B) b0 N% v% s" u# d! N4 M
4、想想我们程序的main函数是由CRT类库进行引导的。在我们现在的设定当中,由
& Y# S# c7 c) e! R0 J- J于采取的是系统缺省的编译连接方式(缺省为编译为Single Thread,Static" t6 [8 h1 J3 @0 F' Z" w
Library),所以,在我们的执行文件当中,包含了CRT的二进制代码。好,修改编
& B; _" x" ]/ o6 l5 ?7 O1 R/ ~ A: Z6 K/ e译选项:C/C++ => Category:Code Generation => Use run-time
; t! f! {1 H9 v+ klibrary:MutiThreaded Dll。编译看看:执行文件大小变成了16,384Bytes。
* L1 |1 M6 f8 C/ _9 P
( n) W" [" {1 f6 \- e0 d5、刚才的设定确实不错,一下子把执行文件大小减小到了16K。现在用UltraEdit$ r& q% r' `: t1 T% [3 X" o) n
看看执行文件都是些什么内容。结果大吃一惊:基本上都是0。看来这个有减小的
& W! j, v9 w# |( ~! I" U4 t必要了。都知道,执行文件都有自己的代码段,数据段等等,每个段的大小也是采, M6 n( P- U* k3 N0 Q# ]& p" A" s
用编译器缺省设定的。好,我们来修改一下段的大小看看:
4 w+ c1 N# w3 i5 Z6 u& a5.1 连接选项中有一个是/opt:nowin98,意思是将段的大小设定成为Win2000适应; G+ d6 H; X) Z; {6 G9 W
的。编译看看:哇塞,变成了2,560byte。看来这个选项确实把文件变小了N多。1 n) d( Q" R$ ]0 |$ y# g
5.2 在查察连接选项中还有没有什么特别的。发现/align:xx还可以将段大小缩
. |. T7 x0 D3 X" [9 k- R. o! A小。通过UltraEdit察看刚才/opt:nowin98编译出来的文件,发现每个段的大小都8 U: ?. ~! }/ c: ]
是4K的整数倍。看来/align:xx还有减小的趋势。试一把再说:添加连接选项:
( k9 \# u/ F) Q! z5 v* T/align:16(这个大小已经是能够设定的最小的了)。看看结果:1,408Bytes。厉( I5 Q! Z, c5 y4 ?) `2 m) t, V
害,现在代码更小了。
h2 ^; j8 Y5 ~2 y! B% ~1 W1 I5 R5.3 现在回想起来,执行文件大小有数据段,执行代码段等等,如果把这些段都合
" v0 u5 v W$ c4 W0 x并起来,是不是就会把段之间的冗余有减小了呢?再试试看:添加选项:
; c8 ?9 Q- ]( f/ z3 y/merge:.data=.text /merge:.rdata=.text。再看看文件大小:1,328bytes。真的
* g' A K5 @8 f很不错了。
- G' f( C1 s- {8 L; j+ k- e) s% H0 r3 D8 _/ g5 q0 ~0 S
6、刚才的设定确实不错,似乎达到了我们想要的极限了。但是回头想一下,如果0 ]7 z" ~+ K7 P- u, m
没有CRT库的话,会不会更小了?实际上确实这样。添加连接选项: /entry:
( g6 u: L" h+ E- n& @9 ymain,把入口地址直接指向我们的main函数看看。得到592Bytes。
6 t P5 [+ t: U+ X* F, r2 d6 e8 {! b0 k j
最终我们得到我们最后的大小592Bytes了。我想这也许是我们通过编译器能够编译7 ?7 { W+ ~$ u$ p( Z4 Y5 R
出来的最小的代码了。
, D4 t" V+ b5 Z; Z. r5 w2 B' O) C! r Q$ Z: B
结论:# {# B" _# s9 z) u
通过上述的步骤,我们了解了如何修改那些编译连接选项来达到执行文件瘦身的目1 I& K( a% O/ D, Y$ D
的。但是,通常来讲,在我们的Release文件当中,并不需要如此小的执行文件。! _0 F1 k: T+ X* B6 _& N
如果想达到瘦身的目的,修改为library:MutiThreaded Dll和添加/opt:nowin98已
' g. Q6 `7 n5 Q- w; z# X经是很好的选择了。其他别的选项在编译的时候或多或少的有警告出现,而且,带$ J8 b4 Y* c' q# l
有那些编译选项编出来的执行文件也不一定在各个平台上能够适用。. x% h8 [3 g& s( O
9 u: { m6 Y/ Q" e) K另外:如果你的执行文件即使通过了这些设定还是比较大的话,也可以通过一些* v1 h$ h8 t. V0 J0 h; r
EXE文件压缩工具来进行压缩。比如UPX等等。在此不再细说了。) y: w! h! Z" c* w
/ r A/ Y9 j- r& E% r; d1 i以上部分的不足之处,还请多多指正。 |
|