|
|
|
在网上,有好多绿色软件,不仅功能强大,而且软件本身的体积非常小。有的通常
: g) s4 y% u4 C1 \只在几十K左右。那他们是怎么做到把软件做的怎么小的呢?现在我手把手的告诉4 I+ o, \6 k' h0 K9 c
你如何通过修改程序的编译选项来瘦身你的执行文件 C9 o1 o5 l- Y! ^0 |
先看一个最典型的程序:
& e% U$ y& `* v# ]+ c# `: |8 _: x#include<stdio.h>
8 t$ p1 i6 P8 B" \. D& D& ]int main()% r+ j; p* s: E* _
{) u% w3 v8 }! Z" z; R% U0 K$ \
printf("Hello,World");
# _* d( \& C0 s" M7 c return 0;3 c3 @0 k! t& V3 w) ^% ~
}
* y! r5 K) H# ?+ ~& D
, [) s2 {4 C8 B! E N4 G5 D5 c/ e上面的程序之所以被称之为典型,是因为他有如下的内容:1 D! P" r* K& y- J
1、系统函数调用:printf
4 W6 A- Q9 T: c g! n/ Y2 {6 O2、有静态数据段
. a# X/ `& [, `+ ^! P6 s# L' H3 |8 N6 j6 _6 X
好,现在把此文件放到VisualStudio6.0中进行编译,看看文件有多大。9 k: s* c1 D2 t- V( {% H
1、用VisualStudio6.0打开HelloWorld.cpp文件,直接按F7。然后点击OK,生成0 I! P' O. x1 o I3 `! v4 J+ u
Project文件,然后进行编译。编译完成了以后,看看Debug目录下的执行文件的大
4 }7 x% p" d. ~, {1 _% h: j5 F6 p% y小,为172,096Bytes。' x, E# ]3 a+ o" r& j' N
3 N$ z6 a" m2 P( j- T
2、刚才编译的Debug文件,现在修改成Release文件看看。选择Win32 Release,再
* q* B- [+ Z2 S8 r* a n' a# @编译。察看执行文件大小,现在成了40,960Bytes。看来Debug版本的要比Release
' p1 k6 t9 z( `/ K, N: g. t的小。
$ z; k% Q7 a: H- o
+ p5 h2 [' k4 Z% f5 z. G8 q3、检查代码优化:发现执行文件的优化是Maximize Speed。那么修改成Minimize: ~& `" | n: t1 J( O; O
Size看看。重新编译,得到执行文件的大小为:40,960Bytes。看来大小没什么变5 @0 a$ C" |$ Z( s0 L" K) Q- k
化。其实这是由于我们的代码本身太小的缘故,导致即使变化了也看不出来。6 ^: P7 V% y: |% ?% j
0 }+ W; \2 U+ ^( y' R+ x$ V
4、想想我们程序的main函数是由CRT类库进行引导的。在我们现在的设定当中,由9 J6 w. \2 z4 k* ^) V. {
于采取的是系统缺省的编译连接方式(缺省为编译为Single Thread,Static
2 `) F* z4 t% B* h7 TLibrary),所以,在我们的执行文件当中,包含了CRT的二进制代码。好,修改编$ U. E! _% }/ T2 B- i
译选项:C/C++ => Category:Code Generation => Use run-time
& g" h5 }. H" ~0 E) P1 {. a. Xlibrary:MutiThreaded Dll。编译看看:执行文件大小变成了16,384Bytes。2 z( G" s" v: [
1 U/ U0 }$ r6 A6 S0 R5、刚才的设定确实不错,一下子把执行文件大小减小到了16K。现在用UltraEdit! {' P( Q! O7 D/ @/ i( c; g
看看执行文件都是些什么内容。结果大吃一惊:基本上都是0。看来这个有减小的
$ c9 i6 a) ?5 U! U. r+ N必要了。都知道,执行文件都有自己的代码段,数据段等等,每个段的大小也是采9 g7 @7 \1 @2 Z2 e8 j( D
用编译器缺省设定的。好,我们来修改一下段的大小看看:/ ~& }) J+ L5 V- |+ C, d
5.1 连接选项中有一个是/opt:nowin98,意思是将段的大小设定成为Win2000适应2 S- Y y8 q1 G% v! c# q4 s
的。编译看看:哇塞,变成了2,560byte。看来这个选项确实把文件变小了N多。4 L8 h( k" K5 Z. O
5.2 在查察连接选项中还有没有什么特别的。发现/align:xx还可以将段大小缩
% L* w2 Y9 O$ F5 k8 q' t小。通过UltraEdit察看刚才/opt:nowin98编译出来的文件,发现每个段的大小都
4 v2 b8 h( I; ~; M0 L是4K的整数倍。看来/align:xx还有减小的趋势。试一把再说:添加连接选项:1 ]+ k4 {; g/ T* ~! t: Y/ G1 ~
/align:16(这个大小已经是能够设定的最小的了)。看看结果:1,408Bytes。厉, t4 {* M5 P" t$ o
害,现在代码更小了。; l$ q$ P2 o! g4 g' C
5.3 现在回想起来,执行文件大小有数据段,执行代码段等等,如果把这些段都合; [1 N2 v, P% H9 O n8 f
并起来,是不是就会把段之间的冗余有减小了呢?再试试看:添加选项:8 {/ u$ M) I/ E. F c8 s9 G
/merge:.data=.text /merge:.rdata=.text。再看看文件大小:1,328bytes。真的
: r# l: s9 l a# i7 V' W4 Q- K很不错了。
+ `7 ~2 ^7 t( p
2 w1 T7 d6 |, W# e6 r/ h. I& g6、刚才的设定确实不错,似乎达到了我们想要的极限了。但是回头想一下,如果
9 E: @( a' o q1 z) e: D7 v6 |没有CRT库的话,会不会更小了?实际上确实这样。添加连接选项: /entry:
7 S1 v. k+ ~% ] X6 ]" Emain,把入口地址直接指向我们的main函数看看。得到592Bytes。
( Y1 h. P5 g7 j! l2 o
& x1 U2 `( Z9 D' R最终我们得到我们最后的大小592Bytes了。我想这也许是我们通过编译器能够编译
5 x% O, U4 T Q, e出来的最小的代码了。! p; z$ d7 d' i# W) @ B6 O; W
' W! z, D* b+ W3 M. K' @
结论:4 P$ k0 N% w: g( t/ N3 }
通过上述的步骤,我们了解了如何修改那些编译连接选项来达到执行文件瘦身的目
0 Q3 i' A- U- F6 {的。但是,通常来讲,在我们的Release文件当中,并不需要如此小的执行文件。6 J) |- V" u2 N3 T+ ?4 v, b
如果想达到瘦身的目的,修改为library:MutiThreaded Dll和添加/opt:nowin98已
$ G; U Z$ H, _ ^ O经是很好的选择了。其他别的选项在编译的时候或多或少的有警告出现,而且,带- c# `) g) ~* y2 J1 Z
有那些编译选项编出来的执行文件也不一定在各个平台上能够适用。, S3 L5 A% l& r+ ?
4 r, p) [9 D- z: q
另外:如果你的执行文件即使通过了这些设定还是比较大的话,也可以通过一些( e" e: [" X' `
EXE文件压缩工具来进行压缩。比如UPX等等。在此不再细说了。
& m5 P7 p% I/ a- [2 }7 T. `' V- d) m
以上部分的不足之处,还请多多指正。 |
|