|
在网上,有好多绿色软件,不仅功能强大,而且软件本身的体积非常小。有的通常
9 |" @1 C. C. ~& w只在几十K左右。那他们是怎么做到把软件做的怎么小的呢?现在我手把手的告诉
! k+ i. t c3 D, l你如何通过修改程序的编译选项来瘦身你的执行文件6 @+ Q' j0 `' [5 W2 ]; y2 t4 \- ]
先看一个最典型的程序:
3 n9 N; F$ z/ e#include<stdio.h>
; \$ r, i5 L+ O* l* bint main()
) r( U# u0 @: t( O{
; {$ n& y+ O! U) D1 K8 j printf("Hello,World");
9 Z, O4 {1 u* { return 0;
7 K* h3 L- X. y5 j}4 k& E& t. i1 i A7 z1 s( U+ ~! k
k( a( h# B4 I7 G& U4 m# ^9 U! g
上面的程序之所以被称之为典型,是因为他有如下的内容:7 ?: v# D6 w5 t( H
1、系统函数调用:printf
# O7 n8 v" `5 I) e1 E" l S2、有静态数据段
+ l9 ?9 l1 D8 F7 n7 n. |8 B4 D7 ^
- p5 s9 O, m% @4 y5 Q& H好,现在把此文件放到VisualStudio6.0中进行编译,看看文件有多大。
8 U3 C. f# M5 Y* X+ i5 D% ^1、用VisualStudio6.0打开HelloWorld.cpp文件,直接按F7。然后点击OK,生成
, Y$ w' u. p% N' E; ^Project文件,然后进行编译。编译完成了以后,看看Debug目录下的执行文件的大5 m; e8 \$ l3 x# X3 \: U
小,为172,096Bytes。( J3 ?4 m) E' C6 Y6 c
3 K, ]8 H! h' y3 \
2、刚才编译的Debug文件,现在修改成Release文件看看。选择Win32 Release,再. k! \9 O3 k* H9 W. Q b3 g" q, z
编译。察看执行文件大小,现在成了40,960Bytes。看来Debug版本的要比Release3 I2 }2 I% L9 P
的小。. ^1 f/ Z6 \5 b- W5 F, C
0 Y! [9 L) `- K% q' F7 A0 D, ]# P3、检查代码优化:发现执行文件的优化是Maximize Speed。那么修改成Minimize0 Y* p5 x/ O& X' P+ U% p
Size看看。重新编译,得到执行文件的大小为:40,960Bytes。看来大小没什么变' B; I. S, f/ j8 d& c/ `6 R0 r* @
化。其实这是由于我们的代码本身太小的缘故,导致即使变化了也看不出来。
' y0 t! e Q* t: `+ P6 ^& D* {' I- W5 B% P h
4、想想我们程序的main函数是由CRT类库进行引导的。在我们现在的设定当中,由
( b2 @/ B) G5 b( W于采取的是系统缺省的编译连接方式(缺省为编译为Single Thread,Static
: j8 I7 Q# O# ?, ]1 e. I; uLibrary),所以,在我们的执行文件当中,包含了CRT的二进制代码。好,修改编
! M7 ~8 \7 L, p! F: ?3 _$ M) b6 N. q9 o译选项:C/C++ => Category:Code Generation => Use run-time
$ b. c% J0 Q7 M: i; K/ b2 f4 c3 ylibrary:MutiThreaded Dll。编译看看:执行文件大小变成了16,384Bytes。
5 j3 {& b; C3 ` w2 {, T5 A6 W4 [
. w& _2 o: Z9 {# ~ [5、刚才的设定确实不错,一下子把执行文件大小减小到了16K。现在用UltraEdit% c2 ]% j% D+ @8 v5 E% z. s, U/ d6 Q
看看执行文件都是些什么内容。结果大吃一惊:基本上都是0。看来这个有减小的
1 T. O( ?. I% [6 s( V必要了。都知道,执行文件都有自己的代码段,数据段等等,每个段的大小也是采' j& j1 x+ Q, ]# X9 l3 `2 K
用编译器缺省设定的。好,我们来修改一下段的大小看看:
2 y3 Q" Y3 F( q, ?0 G2 E5.1 连接选项中有一个是/opt:nowin98,意思是将段的大小设定成为Win2000适应
: J9 |$ w" n6 J7 T" N的。编译看看:哇塞,变成了2,560byte。看来这个选项确实把文件变小了N多。/ J/ r5 t" r5 v+ b2 }8 `
5.2 在查察连接选项中还有没有什么特别的。发现/align:xx还可以将段大小缩8 _0 A( z H" e( ~& j( v
小。通过UltraEdit察看刚才/opt:nowin98编译出来的文件,发现每个段的大小都, X& i% ~4 J# V' V6 d+ ~
是4K的整数倍。看来/align:xx还有减小的趋势。试一把再说:添加连接选项:# c) U2 s$ t4 d4 R9 Q
/align:16(这个大小已经是能够设定的最小的了)。看看结果:1,408Bytes。厉
& H$ Z3 S6 ^' c0 Y/ K% l W害,现在代码更小了。% m6 u! N! R: t. ?0 _' m3 i5 n) y
5.3 现在回想起来,执行文件大小有数据段,执行代码段等等,如果把这些段都合
% N% @3 v" \" {6 s% d2 m: M1 r并起来,是不是就会把段之间的冗余有减小了呢?再试试看:添加选项:2 S/ u- t$ F6 t
/merge:.data=.text /merge:.rdata=.text。再看看文件大小:1,328bytes。真的
3 a7 R6 ] N# s& U3 l0 m1 }, d很不错了。
* E/ F, h/ X9 l: P# c
. \+ f; N5 P1 k6、刚才的设定确实不错,似乎达到了我们想要的极限了。但是回头想一下,如果9 `4 c7 C C+ J
没有CRT库的话,会不会更小了?实际上确实这样。添加连接选项: /entry:) e& C- ]# d; g# p; k. u1 [
main,把入口地址直接指向我们的main函数看看。得到592Bytes。
: u/ n) R( m, {# z# V
6 W. V0 Y1 ~% ]7 I. F. W. a r最终我们得到我们最后的大小592Bytes了。我想这也许是我们通过编译器能够编译
5 q# w- U C# g7 E: s2 i出来的最小的代码了。
! T( {/ ^1 ~7 E! X M" s% M, ^2 V5 W1 v8 g& O
结论:) P& L7 Q3 d7 J5 t/ a3 f; P* v; J
通过上述的步骤,我们了解了如何修改那些编译连接选项来达到执行文件瘦身的目
/ U6 C! L4 |- r$ Q# Z3 `# [# v的。但是,通常来讲,在我们的Release文件当中,并不需要如此小的执行文件。: |/ V H8 M/ l% S' K
如果想达到瘦身的目的,修改为library:MutiThreaded Dll和添加/opt:nowin98已
) B; l) I! b9 _6 p4 I0 x# S经是很好的选择了。其他别的选项在编译的时候或多或少的有警告出现,而且,带- {8 e5 t; K) e' _0 ^+ O- I# W. E
有那些编译选项编出来的执行文件也不一定在各个平台上能够适用。5 v7 O8 J! k' g$ d8 p
* T4 r) S1 y4 S2 z4 f1 c另外:如果你的执行文件即使通过了这些设定还是比较大的话,也可以通过一些/ Q/ u3 I0 d* N! N, v6 e/ A c
EXE文件压缩工具来进行压缩。比如UPX等等。在此不再细说了。
: ?' H- Z, R; v4 K7 d! \0 q8 T
% c. n; s. `8 e9 O i9 x以上部分的不足之处,还请多多指正。 |
|