|
|
|
在网上,有好多绿色软件,不仅功能强大,而且软件本身的体积非常小。有的通常. J# C1 t/ V) d t6 h
只在几十K左右。那他们是怎么做到把软件做的怎么小的呢?现在我手把手的告诉3 |* F6 p: p: D) ^- Z) ~7 Z$ q& N
你如何通过修改程序的编译选项来瘦身你的执行文件% e+ {, v# z( G, Q4 G" i1 Q4 I
先看一个最典型的程序:
6 I5 z8 R6 k9 h" @- N6 o; N#include<stdio.h>
! H, M5 o% z! s {: oint main()
1 b" Q4 _+ C8 S- l W; {4 [{
" [6 }3 K4 R* b* a6 f* a. v2 e printf("Hello,World");
3 L U# m1 J" T0 ?2 B3 T; v return 0;
1 u4 V6 Q; O1 q1 |8 ~ E9 @: \}
5 U0 \! Q* s' G* L! A; s8 `
$ r. j$ I5 S" E上面的程序之所以被称之为典型,是因为他有如下的内容:8 _! |1 I7 `4 @! A1 _
1、系统函数调用:printf5 K) q8 ?/ _2 s5 M6 ?# E+ q+ l
2、有静态数据段% }6 L4 J: l' @) Z0 U' E! E
' ?$ Y6 y; `+ N+ ~& O/ V {
好,现在把此文件放到VisualStudio6.0中进行编译,看看文件有多大。, P2 f, V( V1 r
1、用VisualStudio6.0打开HelloWorld.cpp文件,直接按F7。然后点击OK,生成- }9 O" h* W6 l5 H* m4 F0 |
Project文件,然后进行编译。编译完成了以后,看看Debug目录下的执行文件的大" w% O9 [2 h) D$ U- x
小,为172,096Bytes。( X2 x7 [% R2 }* ^6 M
5 B( g6 v' h$ L2、刚才编译的Debug文件,现在修改成Release文件看看。选择Win32 Release,再1 u8 R% a+ y6 r0 h. s- @
编译。察看执行文件大小,现在成了40,960Bytes。看来Debug版本的要比Release6 ?. R# a4 X P& q" U
的小。
0 ^$ b, `3 a2 v* L6 c0 c5 U
) T$ @3 V' m! e3 ]0 \! l3、检查代码优化:发现执行文件的优化是Maximize Speed。那么修改成Minimize8 u% N0 \; n: ?) ~* e: |
Size看看。重新编译,得到执行文件的大小为:40,960Bytes。看来大小没什么变: ?7 _4 h( V6 V( I% N1 ^" t; Z
化。其实这是由于我们的代码本身太小的缘故,导致即使变化了也看不出来。" A: E/ {- q+ \, Z: O$ e6 M
7 A1 k, v- z' v% H6 J4 F D" \4、想想我们程序的main函数是由CRT类库进行引导的。在我们现在的设定当中,由4 b: b2 J0 i: ]3 D+ \3 F( o. r
于采取的是系统缺省的编译连接方式(缺省为编译为Single Thread,Static! O) g- m: m2 a) Y4 ?! T; k/ A
Library),所以,在我们的执行文件当中,包含了CRT的二进制代码。好,修改编3 t5 c! {( [- w9 M
译选项:C/C++ => Category:Code Generation => Use run-time
9 T/ o, W" T. T, g$ q( Flibrary:MutiThreaded Dll。编译看看:执行文件大小变成了16,384Bytes。
& e6 I5 Q0 ?. V& A, `* W2 i: q. D- U- \* D8 n8 X/ `$ I
5、刚才的设定确实不错,一下子把执行文件大小减小到了16K。现在用UltraEdit
, C, X/ o: o2 [$ l2 r0 _2 Q0 B看看执行文件都是些什么内容。结果大吃一惊:基本上都是0。看来这个有减小的
6 _8 }4 e! t4 N, I1 C必要了。都知道,执行文件都有自己的代码段,数据段等等,每个段的大小也是采
6 ]! }8 U' ~! B. q用编译器缺省设定的。好,我们来修改一下段的大小看看:5 @! F h$ h1 C
5.1 连接选项中有一个是/opt:nowin98,意思是将段的大小设定成为Win2000适应
1 \/ V6 A9 N( R的。编译看看:哇塞,变成了2,560byte。看来这个选项确实把文件变小了N多。
; G0 R5 W6 b& n7 B n* ^$ i: a0 K5.2 在查察连接选项中还有没有什么特别的。发现/align:xx还可以将段大小缩
. ?5 k2 |6 O, U, |+ ]+ R% u% L小。通过UltraEdit察看刚才/opt:nowin98编译出来的文件,发现每个段的大小都5 U5 r# H/ K8 b4 J6 O
是4K的整数倍。看来/align:xx还有减小的趋势。试一把再说:添加连接选项:
1 |8 j2 F: M. H3 P/align:16(这个大小已经是能够设定的最小的了)。看看结果:1,408Bytes。厉
/ C5 ] z# O5 A害,现在代码更小了。. F: W/ L9 e& {- D
5.3 现在回想起来,执行文件大小有数据段,执行代码段等等,如果把这些段都合
! p4 I% w6 i/ {9 x9 `4 a并起来,是不是就会把段之间的冗余有减小了呢?再试试看:添加选项:
% _/ X. _$ J; ~8 ]/merge:.data=.text /merge:.rdata=.text。再看看文件大小:1,328bytes。真的. A' |( ^+ @! K0 h% K
很不错了。
3 V- V8 R. T, I7 q, @) f9 y) L5 ~! b- ?* K3 y; D4 }( V# t# c
6、刚才的设定确实不错,似乎达到了我们想要的极限了。但是回头想一下,如果! k- K4 u( P- A8 V; F+ I @
没有CRT库的话,会不会更小了?实际上确实这样。添加连接选项: /entry:
5 W7 s' v0 i& J: Zmain,把入口地址直接指向我们的main函数看看。得到592Bytes。' L% u* y1 o4 \/ l( Q$ [6 B6 u
/ K4 ~; q7 P" m" l( @最终我们得到我们最后的大小592Bytes了。我想这也许是我们通过编译器能够编译
2 I, A5 J5 {+ Y' G/ D0 l, v出来的最小的代码了。
7 a# G/ \8 y+ g O5 f+ \9 @
: H( i7 W& q; S4 c. d结论:
6 u8 P0 r' ^) D+ o9 ~9 F. A3 X8 S通过上述的步骤,我们了解了如何修改那些编译连接选项来达到执行文件瘦身的目! t: z2 _6 W, ]6 N
的。但是,通常来讲,在我们的Release文件当中,并不需要如此小的执行文件。
! }0 U* a. Z+ x! P如果想达到瘦身的目的,修改为library:MutiThreaded Dll和添加/opt:nowin98已* c; |4 D6 a$ O4 L$ P
经是很好的选择了。其他别的选项在编译的时候或多或少的有警告出现,而且,带
' L$ X7 E; ~+ [, t有那些编译选项编出来的执行文件也不一定在各个平台上能够适用。
' F( `, C( {9 w8 K8 H1 N4 s
% }/ J0 M% e6 o, t" O& g5 a另外:如果你的执行文件即使通过了这些设定还是比较大的话,也可以通过一些
) q+ P9 r' v: G% M2 k) gEXE文件压缩工具来进行压缩。比如UPX等等。在此不再细说了。/ O$ B6 r6 v/ q. I
2 d' ^- \! z- ^7 K+ l$ \: X5 W* r
以上部分的不足之处,还请多多指正。 |
|