|
|
|
在网上,有好多绿色软件,不仅功能强大,而且软件本身的体积非常小。有的通常' i2 }$ M+ Y8 m0 Q! A8 X' O5 P
只在几十K左右。那他们是怎么做到把软件做的怎么小的呢?现在我手把手的告诉
& s7 s3 D" X9 l* R9 P4 f1 `你如何通过修改程序的编译选项来瘦身你的执行文件3 W( \' g5 c# V0 r
先看一个最典型的程序:
( x" D0 i/ _7 y0 l: U: ~#include<stdio.h>) C, k+ O! N9 p u
int main()/ O4 b5 D. V, w+ S' v, m6 H. [
{
* [" h5 l5 q( ]4 u printf("Hello,World");, ?) O6 y1 e- d& P. M1 {
return 0;+ W/ [+ u) f4 }# Y% k% }
}
) _: c2 @% w) ]& v+ x. m
% }3 v0 o' E' |- c& W0 Q0 ?: I8 I上面的程序之所以被称之为典型,是因为他有如下的内容:
5 R0 |2 g* O2 H8 x( \1、系统函数调用:printf
: @* U0 `* k9 k3 d% Q! D8 i* R2、有静态数据段8 x. y8 s" h2 }1 O0 g) d! W5 K
8 f% E! [; j; X* E8 `8 @
好,现在把此文件放到VisualStudio6.0中进行编译,看看文件有多大。
3 q9 B# O% J1 p* T; i6 R+ H1 i1、用VisualStudio6.0打开HelloWorld.cpp文件,直接按F7。然后点击OK,生成
1 R) V2 B5 W' H# A& lProject文件,然后进行编译。编译完成了以后,看看Debug目录下的执行文件的大" B' h% N1 p5 M) G2 c* c
小,为172,096Bytes。. G( q2 N8 B/ h% G( {# A
. r, o: I) Y1 Y; q- O
2、刚才编译的Debug文件,现在修改成Release文件看看。选择Win32 Release,再
2 c" Q+ i* b5 E; G) q编译。察看执行文件大小,现在成了40,960Bytes。看来Debug版本的要比Release% k2 N( [% ?( a
的小。
% A2 A; b* Y0 s0 }: }6 g' Y- Y
( E+ R0 M" a9 ~( z( s, K6 p X3、检查代码优化:发现执行文件的优化是Maximize Speed。那么修改成Minimize; M; C. A4 O1 f7 t+ J3 C" y
Size看看。重新编译,得到执行文件的大小为:40,960Bytes。看来大小没什么变
8 s1 X9 [1 g) j! |5 }$ \4 q化。其实这是由于我们的代码本身太小的缘故,导致即使变化了也看不出来。
( C9 s2 x0 ]# @
, a( c; S) O$ u: C& P" v4、想想我们程序的main函数是由CRT类库进行引导的。在我们现在的设定当中,由
. {# D6 L% i, U于采取的是系统缺省的编译连接方式(缺省为编译为Single Thread,Static- j: R, U3 Z, m
Library),所以,在我们的执行文件当中,包含了CRT的二进制代码。好,修改编3 R/ |4 L# `# f% f {! U
译选项:C/C++ => Category:Code Generation => Use run-time
/ f/ k. R. l2 I/ Y: a: e+ jlibrary:MutiThreaded Dll。编译看看:执行文件大小变成了16,384Bytes。, p! V5 b- \% N+ f. S3 q& {
" E: H0 W& u3 f4 K
5、刚才的设定确实不错,一下子把执行文件大小减小到了16K。现在用UltraEdit
* F& r' |5 P2 v# C' X/ C看看执行文件都是些什么内容。结果大吃一惊:基本上都是0。看来这个有减小的
; q7 ?" C, g" F0 g' x3 K必要了。都知道,执行文件都有自己的代码段,数据段等等,每个段的大小也是采
+ g8 v+ J/ U% A Q* t3 e用编译器缺省设定的。好,我们来修改一下段的大小看看:
2 T( d5 u% @' G' f" |5.1 连接选项中有一个是/opt:nowin98,意思是将段的大小设定成为Win2000适应
+ h. ~/ |% {, M& y+ P; ?* H' N' l的。编译看看:哇塞,变成了2,560byte。看来这个选项确实把文件变小了N多。+ S+ v a, z4 n% a- A7 q* d
5.2 在查察连接选项中还有没有什么特别的。发现/align:xx还可以将段大小缩, i: k. a, Y K0 F: R
小。通过UltraEdit察看刚才/opt:nowin98编译出来的文件,发现每个段的大小都
# O9 z$ N/ ]5 F! b! A是4K的整数倍。看来/align:xx还有减小的趋势。试一把再说:添加连接选项:% ^, S$ U' C' H/ P' y$ d# Q
/align:16(这个大小已经是能够设定的最小的了)。看看结果:1,408Bytes。厉
$ j( y" \; [/ c4 z2 K0 j害,现在代码更小了。) j: ~2 A m' O" E2 t& Y- i' a
5.3 现在回想起来,执行文件大小有数据段,执行代码段等等,如果把这些段都合9 s& @1 }" Q6 L; ]3 w
并起来,是不是就会把段之间的冗余有减小了呢?再试试看:添加选项:
; z& K( ~) i5 d; V6 o- h: D: g" G/merge:.data=.text /merge:.rdata=.text。再看看文件大小:1,328bytes。真的. ~+ v: P: y5 ^: V6 q; Y
很不错了。3 L3 y: W' F# w: t3 U, o# J
9 ^7 a( s: T. s& o0 a6、刚才的设定确实不错,似乎达到了我们想要的极限了。但是回头想一下,如果0 t' i* h' Q, Y- c2 v. W; }
没有CRT库的话,会不会更小了?实际上确实这样。添加连接选项: /entry:) p$ w" }5 w, ~3 a5 ?
main,把入口地址直接指向我们的main函数看看。得到592Bytes。
8 x- K2 ?* A; I9 Y: N4 r
$ `3 Z. l; T1 L- d: D1 |最终我们得到我们最后的大小592Bytes了。我想这也许是我们通过编译器能够编译 |+ o3 E7 I, H
出来的最小的代码了。$ W$ H( j# c+ I5 H
3 ?1 T! \3 _; o* _, b" q, x+ K
结论:
; o+ C$ _7 F3 E# r1 I& G通过上述的步骤,我们了解了如何修改那些编译连接选项来达到执行文件瘦身的目' b) Q" P/ G, O
的。但是,通常来讲,在我们的Release文件当中,并不需要如此小的执行文件。# \$ Y: c3 I1 g1 U1 `0 ~$ V3 Y, z# Y
如果想达到瘦身的目的,修改为library:MutiThreaded Dll和添加/opt:nowin98已
* u6 W, G) n# t" h) Q: B- `1 w经是很好的选择了。其他别的选项在编译的时候或多或少的有警告出现,而且,带, p, _( g& A' U! U$ @
有那些编译选项编出来的执行文件也不一定在各个平台上能够适用。0 w) y; x+ t Q) y! `& n- u/ J; X
+ ~; P7 L$ F6 N: T9 w# U另外:如果你的执行文件即使通过了这些设定还是比较大的话,也可以通过一些
* O [, N2 l1 K; q$ V4 n7 qEXE文件压缩工具来进行压缩。比如UPX等等。在此不再细说了。
. P& o- Q9 G; G+ ~8 t, L* G; `0 n' N5 v- B5 D, t5 n5 }
以上部分的不足之处,还请多多指正。 |
|