|
|
|
在网上,有好多绿色软件,不仅功能强大,而且软件本身的体积非常小。有的通常
8 b) `. A+ w& u P只在几十K左右。那他们是怎么做到把软件做的怎么小的呢?现在我手把手的告诉
0 G7 |4 L6 G. l0 Y* L$ }- j你如何通过修改程序的编译选项来瘦身你的执行文件
. L; O6 O6 c7 C5 X: k" i5 i先看一个最典型的程序: ; {" ]$ m6 t Q+ u# T' K* P I6 m
#include<stdio.h>
1 R, ?5 k4 [$ N8 f* I1 jint main()
$ F) {: j6 d: m0 P9 F0 Y/ O& @{" n$ b: \. ~' J1 G% K; E
printf("Hello,World");
3 f$ l; Q" c0 T; O return 0;
6 a; E; B$ {2 Q6 _; }0 q) N- Y}
- `9 b9 ?7 T* W q; V1 b& {( z
9 z' [4 ~0 a) o6 P* X+ t, @上面的程序之所以被称之为典型,是因为他有如下的内容:" C# M8 W) ^, @2 Y
1、系统函数调用:printf$ V0 F: J% G/ h/ Q% d/ G
2、有静态数据段$ S T# y0 j4 W
; a% f7 V& d0 I7 a' B好,现在把此文件放到VisualStudio6.0中进行编译,看看文件有多大。
2 C$ l' F ~' y. c1、用VisualStudio6.0打开HelloWorld.cpp文件,直接按F7。然后点击OK,生成+ g' q2 d! ?4 U
Project文件,然后进行编译。编译完成了以后,看看Debug目录下的执行文件的大, L: o5 V9 s+ X) y1 `( [% r
小,为172,096Bytes。
3 [, V1 Y1 q3 t- e1 y9 n- A% T1 B/ B5 |; k8 T) d6 S
2、刚才编译的Debug文件,现在修改成Release文件看看。选择Win32 Release,再4 B- Y4 H. u; r
编译。察看执行文件大小,现在成了40,960Bytes。看来Debug版本的要比Release
7 c( U6 a/ y2 O# I的小。
/ J; L. L# t& v' u3 `2 s( N8 I% N' G# L. Q, o/ g8 N5 Z
3、检查代码优化:发现执行文件的优化是Maximize Speed。那么修改成Minimize
0 i( S) b; o) `' O& bSize看看。重新编译,得到执行文件的大小为:40,960Bytes。看来大小没什么变6 Z% L+ l$ B2 {7 T; @, Q0 p
化。其实这是由于我们的代码本身太小的缘故,导致即使变化了也看不出来。
1 H' t9 M, z4 B7 _' [3 V0 F9 f# X& R% I( @! P
4、想想我们程序的main函数是由CRT类库进行引导的。在我们现在的设定当中,由* f1 i2 a) b2 N" [$ f- g7 |! c
于采取的是系统缺省的编译连接方式(缺省为编译为Single Thread,Static
+ k+ e7 u i0 r% o mLibrary),所以,在我们的执行文件当中,包含了CRT的二进制代码。好,修改编# m* W( x% P. v
译选项:C/C++ => Category:Code Generation => Use run-time
' W" X7 c4 J7 i' D1 n7 a; Mlibrary:MutiThreaded Dll。编译看看:执行文件大小变成了16,384Bytes。
, B. u' u4 D3 d: i @2 O0 k
v7 t% }5 w+ b. J* G5、刚才的设定确实不错,一下子把执行文件大小减小到了16K。现在用UltraEdit
4 ^& D. H' u+ E* O2 b# \8 O0 O1 b看看执行文件都是些什么内容。结果大吃一惊:基本上都是0。看来这个有减小的$ [+ S' I$ C: A( Z4 V9 B& \
必要了。都知道,执行文件都有自己的代码段,数据段等等,每个段的大小也是采9 p% ?) Y1 j4 K8 }0 A
用编译器缺省设定的。好,我们来修改一下段的大小看看:
. [7 f! M1 Z! v/ p+ `# n5.1 连接选项中有一个是/opt:nowin98,意思是将段的大小设定成为Win2000适应
( R7 j; _/ d- i7 ~0 ? k的。编译看看:哇塞,变成了2,560byte。看来这个选项确实把文件变小了N多。
! u5 r2 {; q6 T" V! J5.2 在查察连接选项中还有没有什么特别的。发现/align:xx还可以将段大小缩( w/ L* s6 T8 A8 \4 O' }
小。通过UltraEdit察看刚才/opt:nowin98编译出来的文件,发现每个段的大小都
1 h. V# a1 g) v7 s4 G# S- F是4K的整数倍。看来/align:xx还有减小的趋势。试一把再说:添加连接选项:
+ I- f8 W8 M6 X7 I5 K/align:16(这个大小已经是能够设定的最小的了)。看看结果:1,408Bytes。厉
( ~+ \! A" F/ j5 S+ ?7 S h @- ~害,现在代码更小了。* N" O5 {' [7 D% _
5.3 现在回想起来,执行文件大小有数据段,执行代码段等等,如果把这些段都合) Y4 @, `) b8 g& _
并起来,是不是就会把段之间的冗余有减小了呢?再试试看:添加选项:
$ u6 G! B' F- [1 n& o+ F/merge:.data=.text /merge:.rdata=.text。再看看文件大小:1,328bytes。真的" C3 b# K* U) @4 }
很不错了。
' B6 D2 o2 J( |, P8 m3 G5 r+ d" M- m. P' |: y# b" @1 w1 H, \; B4 P+ T
6、刚才的设定确实不错,似乎达到了我们想要的极限了。但是回头想一下,如果
7 L& x( [# s1 f$ B# P5 \( J, C没有CRT库的话,会不会更小了?实际上确实这样。添加连接选项: /entry:
! W5 D z7 ?! |+ ~: v' o8 qmain,把入口地址直接指向我们的main函数看看。得到592Bytes。
* W" p( P3 _1 X4 ~2 w- t9 k1 z4 S m6 |! f; e( k1 _
最终我们得到我们最后的大小592Bytes了。我想这也许是我们通过编译器能够编译7 M" ^, i" D7 `6 `# |# D4 W3 }: U
出来的最小的代码了。/ {! k, q3 G( T, ], U) O
" {7 S% A6 h: \结论:
1 [( |3 H3 q9 T, N! G通过上述的步骤,我们了解了如何修改那些编译连接选项来达到执行文件瘦身的目
2 l% k" l+ u7 w3 {的。但是,通常来讲,在我们的Release文件当中,并不需要如此小的执行文件。( s! z4 k' F( ^7 i
如果想达到瘦身的目的,修改为library:MutiThreaded Dll和添加/opt:nowin98已+ }0 b) l- p# o5 [2 g" o i- g
经是很好的选择了。其他别的选项在编译的时候或多或少的有警告出现,而且,带
% ?; q* a8 a6 }9 [6 q4 Q! \有那些编译选项编出来的执行文件也不一定在各个平台上能够适用。- \0 x5 }# K) \3 T
6 q2 N1 }& c& P: r另外:如果你的执行文件即使通过了这些设定还是比较大的话,也可以通过一些
) b7 f$ T' a6 V( U9 e1 A! I: i, OEXE文件压缩工具来进行压缩。比如UPX等等。在此不再细说了。
: ]) `+ o. @; i6 _* R- F* ~: e" Y9 ^9 |+ Z/ p% z
以上部分的不足之处,还请多多指正。 |
|