|
|
|
在网上,有好多绿色软件,不仅功能强大,而且软件本身的体积非常小。有的通常* y4 _3 E8 j T; b4 t
只在几十K左右。那他们是怎么做到把软件做的怎么小的呢?现在我手把手的告诉
2 p2 J R. }: v1 K你如何通过修改程序的编译选项来瘦身你的执行文件 P. Q, w1 i0 j1 n+ E
先看一个最典型的程序:
9 U/ O* E! s& G8 s- |3 T1 i#include<stdio.h>
- ]& D' Z' u# Y6 s& g wint main()
7 u; P! t' I4 @+ F- y+ ~{' Y7 r9 ]) O* k* r/ t' s
printf("Hello,World");
" f# v7 F. K C return 0;
$ V! v6 j. u* w) d5 I, w7 v}( k+ \% X& W; Z( H9 l% I/ Q, O
# h5 F& k& Z! N0 z( j上面的程序之所以被称之为典型,是因为他有如下的内容:/ e1 j( `5 }1 C& s. @. n( ?
1、系统函数调用:printf/ W8 P# [* z/ Q2 T
2、有静态数据段
9 S% w2 V7 n K6 h* z
6 o# H8 [8 A# w3 [2 K2 p, F" D好,现在把此文件放到VisualStudio6.0中进行编译,看看文件有多大。
1 B/ I- z6 D9 V! Q0 p7 z0 [9 @* w1、用VisualStudio6.0打开HelloWorld.cpp文件,直接按F7。然后点击OK,生成
3 y& C$ f( H: eProject文件,然后进行编译。编译完成了以后,看看Debug目录下的执行文件的大" P7 o4 L2 K; X* R
小,为172,096Bytes。/ N3 e d7 r* e4 w
2 |/ f# f! \" @
2、刚才编译的Debug文件,现在修改成Release文件看看。选择Win32 Release,再- V% G, U( R; x: K, ~& c
编译。察看执行文件大小,现在成了40,960Bytes。看来Debug版本的要比Release6 X* z8 M' U6 l P* {0 ~+ s
的小。0 V( `" w( C1 v& _( ~+ F2 C
( i- \' `. U+ T' [) m8 z# w3、检查代码优化:发现执行文件的优化是Maximize Speed。那么修改成Minimize
$ D, ?+ D, i+ Y" u( HSize看看。重新编译,得到执行文件的大小为:40,960Bytes。看来大小没什么变9 X; L" f" C u
化。其实这是由于我们的代码本身太小的缘故,导致即使变化了也看不出来。, ?% x& L8 ~4 R2 X' W
# A0 h) g9 y, b F) O4、想想我们程序的main函数是由CRT类库进行引导的。在我们现在的设定当中,由
) `, ~* X8 ?! T% ~7 j0 c于采取的是系统缺省的编译连接方式(缺省为编译为Single Thread,Static
$ a: O: R2 ?( v3 KLibrary),所以,在我们的执行文件当中,包含了CRT的二进制代码。好,修改编& [- k, r, Y7 J% ]* y
译选项:C/C++ => Category:Code Generation => Use run-time* u0 } |, \/ K& x) e7 [2 L
library:MutiThreaded Dll。编译看看:执行文件大小变成了16,384Bytes。
9 i) B0 G0 y, T1 f8 q: A, h ?; q8 A _% Y/ v/ m, ]) @
5、刚才的设定确实不错,一下子把执行文件大小减小到了16K。现在用UltraEdit4 [6 Z* y7 H- \6 S% H) ` R
看看执行文件都是些什么内容。结果大吃一惊:基本上都是0。看来这个有减小的) [ M; q& V8 t
必要了。都知道,执行文件都有自己的代码段,数据段等等,每个段的大小也是采1 K) g5 S8 [, c; X9 H/ K
用编译器缺省设定的。好,我们来修改一下段的大小看看:
f: E( I3 D2 B. u5.1 连接选项中有一个是/opt:nowin98,意思是将段的大小设定成为Win2000适应
& \" K7 v8 s' e' S5 M w" [- x: e2 i6 ?的。编译看看:哇塞,变成了2,560byte。看来这个选项确实把文件变小了N多。$ V% ?1 a$ B# ] u; Y" C, o. |
5.2 在查察连接选项中还有没有什么特别的。发现/align:xx还可以将段大小缩& {: S8 x3 f5 j2 E) j2 ]. R
小。通过UltraEdit察看刚才/opt:nowin98编译出来的文件,发现每个段的大小都: T1 f. P* h+ [1 u# @
是4K的整数倍。看来/align:xx还有减小的趋势。试一把再说:添加连接选项:
1 X! ]; f7 V2 o5 P F# _( N/align:16(这个大小已经是能够设定的最小的了)。看看结果:1,408Bytes。厉( C! x% [7 O9 n I3 N! O
害,现在代码更小了。) K1 I S7 U% B
5.3 现在回想起来,执行文件大小有数据段,执行代码段等等,如果把这些段都合
% f: }5 _4 S* Y. [% D0 u# }; ?并起来,是不是就会把段之间的冗余有减小了呢?再试试看:添加选项:
; C" G Y/ E3 E$ Q0 G8 C! u$ R/merge:.data=.text /merge:.rdata=.text。再看看文件大小:1,328bytes。真的
$ _2 Y8 W2 T& a) M很不错了。9 u' z% d6 r* E8 |/ _/ `" x7 S
, B2 Y# _: y# l3 V* E
6、刚才的设定确实不错,似乎达到了我们想要的极限了。但是回头想一下,如果3 N* G3 l# ~. x. B
没有CRT库的话,会不会更小了?实际上确实这样。添加连接选项: /entry:0 n7 f# h1 Z h
main,把入口地址直接指向我们的main函数看看。得到592Bytes。5 i" L) m9 ^4 o2 P
l- M! y; s$ a( z% n
最终我们得到我们最后的大小592Bytes了。我想这也许是我们通过编译器能够编译
. [4 O( u9 u9 Y+ _4 x9 P4 B出来的最小的代码了。
; }" j; l7 l/ j* e# O% `; N- x- |6 s2 M+ Y7 Y
结论:
4 T2 O$ `, R' W+ e通过上述的步骤,我们了解了如何修改那些编译连接选项来达到执行文件瘦身的目
4 m0 d1 Z* [* _0 l, p% B的。但是,通常来讲,在我们的Release文件当中,并不需要如此小的执行文件。
% |: U F6 f# Q如果想达到瘦身的目的,修改为library:MutiThreaded Dll和添加/opt:nowin98已7 M1 K& a0 q2 U! r3 u3 |
经是很好的选择了。其他别的选项在编译的时候或多或少的有警告出现,而且,带4 D B2 f2 m( e/ v1 ]
有那些编译选项编出来的执行文件也不一定在各个平台上能够适用。
/ m1 _& N# Z6 `, A, D& P5 Q1 g- N! L0 P0 z H5 T& \ R
另外:如果你的执行文件即使通过了这些设定还是比较大的话,也可以通过一些( d+ u9 a! q7 A* |3 p: h4 \
EXE文件压缩工具来进行压缩。比如UPX等等。在此不再细说了。$ }# N1 \8 J# c6 v P% @8 b! t
6 O& u! X4 b& o' W# C$ O! D
以上部分的不足之处,还请多多指正。 |
|