|
|
|
在网上,有好多绿色软件,不仅功能强大,而且软件本身的体积非常小。有的通常
. A, v: G K6 y1 P. R只在几十K左右。那他们是怎么做到把软件做的怎么小的呢?现在我手把手的告诉, c( ]; O3 _ \5 Q8 d
你如何通过修改程序的编译选项来瘦身你的执行文件5 Y8 W' C5 o8 k) G
先看一个最典型的程序: ; s" ], W0 e) E! I
#include<stdio.h>! h$ O2 ?2 C+ ]7 b9 Q) X
int main()
) b4 }4 B4 p0 @{
4 b; G. ^1 A1 _: e/ b printf("Hello,World");
: u1 M, a0 H1 M1 B( Z; F return 0;4 G% S! J( \: A7 s
}3 H: O' w" J2 T# k2 ^
' a& b) B6 ~& T4 [, R5 \- p
上面的程序之所以被称之为典型,是因为他有如下的内容:* a8 G# [( x W) r
1、系统函数调用:printf
Z7 N& N' L5 h' c% P/ V4 B, @2、有静态数据段
8 K, `# `6 G4 }' [, Y5 g
* p# Q( R0 x y; R4 c m' n- |好,现在把此文件放到VisualStudio6.0中进行编译,看看文件有多大。
. T: T& J% k0 `+ \8 A$ y1、用VisualStudio6.0打开HelloWorld.cpp文件,直接按F7。然后点击OK,生成' E i) Y/ U) n# P! _
Project文件,然后进行编译。编译完成了以后,看看Debug目录下的执行文件的大* H; `7 ^2 x7 Y6 Y$ p! r
小,为172,096Bytes。
; m7 A* t T+ ~3 g7 f- k; c/ B5 V" c# q# d9 N. p' l
2、刚才编译的Debug文件,现在修改成Release文件看看。选择Win32 Release,再
3 a! ] v/ G. B/ P% M3 b2 u0 A& I编译。察看执行文件大小,现在成了40,960Bytes。看来Debug版本的要比Release# d) |0 x+ P+ ^9 L; U
的小。% K i" _" N4 [" ?
% }1 H0 n* z4 z7 B3 H7 V5 X
3、检查代码优化:发现执行文件的优化是Maximize Speed。那么修改成Minimize
4 E! U0 f6 x3 `8 NSize看看。重新编译,得到执行文件的大小为:40,960Bytes。看来大小没什么变
+ G% K3 t+ [4 _1 `4 k化。其实这是由于我们的代码本身太小的缘故,导致即使变化了也看不出来。" C! H% ^: x, ? y
( m- A# C1 [6 h3 F. ^) D
4、想想我们程序的main函数是由CRT类库进行引导的。在我们现在的设定当中,由
% B( Y" N m& R/ a% q于采取的是系统缺省的编译连接方式(缺省为编译为Single Thread,Static
3 p4 }' A. f, j& I% l5 lLibrary),所以,在我们的执行文件当中,包含了CRT的二进制代码。好,修改编
. \8 W7 ]" g# Y! L D/ R+ \译选项:C/C++ => Category:Code Generation => Use run-time
. P. G* E5 U" @$ [6 n3 blibrary:MutiThreaded Dll。编译看看:执行文件大小变成了16,384Bytes。$ s, |7 Z6 H% U* A/ l+ i
% g5 ]: X+ ?; K4 Y8 e. P7 v, o
5、刚才的设定确实不错,一下子把执行文件大小减小到了16K。现在用UltraEdit' w7 h9 ]8 q5 L9 g
看看执行文件都是些什么内容。结果大吃一惊:基本上都是0。看来这个有减小的
0 {* f0 u2 d0 b2 p/ `$ R必要了。都知道,执行文件都有自己的代码段,数据段等等,每个段的大小也是采
d! p+ j, M; N4 H5 p用编译器缺省设定的。好,我们来修改一下段的大小看看:. q7 R. \: v* Z$ K4 `8 a0 O
5.1 连接选项中有一个是/opt:nowin98,意思是将段的大小设定成为Win2000适应* o$ Q7 Q7 w( @0 A
的。编译看看:哇塞,变成了2,560byte。看来这个选项确实把文件变小了N多。5 }1 V) Y/ Q9 q) L
5.2 在查察连接选项中还有没有什么特别的。发现/align:xx还可以将段大小缩' y" R6 r% K# T6 ^" _' }
小。通过UltraEdit察看刚才/opt:nowin98编译出来的文件,发现每个段的大小都* I. s0 ^4 J% ]5 w. |/ V4 Y; _' P
是4K的整数倍。看来/align:xx还有减小的趋势。试一把再说:添加连接选项:
, u, A& m, v, u/align:16(这个大小已经是能够设定的最小的了)。看看结果:1,408Bytes。厉
7 g, q3 X' P9 T" |% D* k害,现在代码更小了。7 X. ~/ E; n+ {0 E4 J' ]; T
5.3 现在回想起来,执行文件大小有数据段,执行代码段等等,如果把这些段都合
6 l4 N0 K- }$ u" j4 I并起来,是不是就会把段之间的冗余有减小了呢?再试试看:添加选项:0 w7 y3 f8 T$ w7 H5 e& ~. L6 P, {
/merge:.data=.text /merge:.rdata=.text。再看看文件大小:1,328bytes。真的
6 `1 U9 A5 w# o" w很不错了。1 C1 v$ A$ C; x. N/ L! E
9 G' ^$ F# I& B( }2 W1 M0 }
6、刚才的设定确实不错,似乎达到了我们想要的极限了。但是回头想一下,如果- T. z" I0 q% J( U3 K0 H. _
没有CRT库的话,会不会更小了?实际上确实这样。添加连接选项: /entry:# m7 @* c9 H, O0 R/ j8 {, P/ t
main,把入口地址直接指向我们的main函数看看。得到592Bytes。
" w; i+ L1 y( U( p
. @0 r; w( h" s3 o' t4 l6 j最终我们得到我们最后的大小592Bytes了。我想这也许是我们通过编译器能够编译, P! L" J3 j+ L) ?
出来的最小的代码了。$ Z9 J# s4 |; j
4 o5 b0 ]( v; F* K, L" u' {结论:
: V0 [( A7 `7 x' C通过上述的步骤,我们了解了如何修改那些编译连接选项来达到执行文件瘦身的目
, d+ j3 l0 U: K/ D0 N7 X的。但是,通常来讲,在我们的Release文件当中,并不需要如此小的执行文件。& Q& {: u3 I R
如果想达到瘦身的目的,修改为library:MutiThreaded Dll和添加/opt:nowin98已
1 ]- [6 W9 g5 q9 b+ s经是很好的选择了。其他别的选项在编译的时候或多或少的有警告出现,而且,带
! Y, D; j1 C4 b. m4 I N) i% |! F- K5 t有那些编译选项编出来的执行文件也不一定在各个平台上能够适用。3 q: V. q l. \( I6 S5 Z
6 B! i, r1 u6 j( E/ c
另外:如果你的执行文件即使通过了这些设定还是比较大的话,也可以通过一些( k! e9 @4 f& W5 I: h9 N! T
EXE文件压缩工具来进行压缩。比如UPX等等。在此不再细说了。) Q1 Q3 R" W! x' f
6 A8 T I! g' ]! X1 D. |% f, Q以上部分的不足之处,还请多多指正。 |
|