|
|
|
在网上,有好多绿色软件,不仅功能强大,而且软件本身的体积非常小。有的通常
! O' B# k6 S9 L U; ^3 K% l只在几十K左右。那他们是怎么做到把软件做的怎么小的呢?现在我手把手的告诉. r" Y7 x m+ b8 w* a. l. e6 c
你如何通过修改程序的编译选项来瘦身你的执行文件% k3 `* T' a- x5 G9 R; w
先看一个最典型的程序: # X) ^0 v( \( v
#include<stdio.h>: D. R, p' z9 U0 f |
int main()
' P+ |, q+ f$ t{1 g) x) Z: x+ M D/ j0 D: L
printf("Hello,World");
+ Y5 p# E1 }8 U return 0;
6 u4 I3 @. @. C; Y}
$ [$ {+ U" B* z% S/ M
; t9 w) q) Y' j W: A! j- S上面的程序之所以被称之为典型,是因为他有如下的内容:) }6 ?6 S9 x8 C- c9 G
1、系统函数调用:printf3 Z$ o; `1 A" w1 z P6 }5 r
2、有静态数据段
. [9 E* B3 l; l) ]: f0 Z" ?; ?" N3 n+ P% I, T" t& t
好,现在把此文件放到VisualStudio6.0中进行编译,看看文件有多大。
7 ~' L9 j- B# Y( n/ M$ g" t/ Z1、用VisualStudio6.0打开HelloWorld.cpp文件,直接按F7。然后点击OK,生成8 `5 d# E4 q; W$ X0 t0 q
Project文件,然后进行编译。编译完成了以后,看看Debug目录下的执行文件的大
" P& p# A' }0 m- e7 D小,为172,096Bytes。
N( V: G% \! U4 e) D. n
1 D) q) t& m; n$ d1 U2、刚才编译的Debug文件,现在修改成Release文件看看。选择Win32 Release,再
6 m* i" o$ X# f9 k编译。察看执行文件大小,现在成了40,960Bytes。看来Debug版本的要比Release
* Z; F5 R1 l) m E的小。
0 n1 o7 T$ y. Y' B, k3 t1 G
/ Z( g3 a: T5 R/ @8 a3、检查代码优化:发现执行文件的优化是Maximize Speed。那么修改成Minimize
1 [7 r) l/ y1 q$ `Size看看。重新编译,得到执行文件的大小为:40,960Bytes。看来大小没什么变7 b) Z' }9 o- i3 k# W
化。其实这是由于我们的代码本身太小的缘故,导致即使变化了也看不出来。
: P5 g/ r/ d4 j7 L( f& |+ w# |+ f
7 S% S( J6 p: O, Y; i: a' U) g4、想想我们程序的main函数是由CRT类库进行引导的。在我们现在的设定当中,由. t8 l- v* j @8 p
于采取的是系统缺省的编译连接方式(缺省为编译为Single Thread,Static
' ]* C6 T. Y' S; d& w4 YLibrary),所以,在我们的执行文件当中,包含了CRT的二进制代码。好,修改编3 @* J Z1 ]+ q! Y, Y
译选项:C/C++ => Category:Code Generation => Use run-time
% y3 \9 n5 S! j( o' @library:MutiThreaded Dll。编译看看:执行文件大小变成了16,384Bytes。
. A* D4 p d% }8 Y9 k( i) Z2 v, Z- a7 {9 }7 H1 T* s3 a
5、刚才的设定确实不错,一下子把执行文件大小减小到了16K。现在用UltraEdit
8 ^4 A7 e# _9 }3 h看看执行文件都是些什么内容。结果大吃一惊:基本上都是0。看来这个有减小的
# I1 V/ B% |+ u$ d必要了。都知道,执行文件都有自己的代码段,数据段等等,每个段的大小也是采
% I$ C/ F: ]2 d- T" u用编译器缺省设定的。好,我们来修改一下段的大小看看:
$ c: h7 }$ C C2 q' A, Y- m5.1 连接选项中有一个是/opt:nowin98,意思是将段的大小设定成为Win2000适应7 @: b* }& R. c9 x( Q8 H
的。编译看看:哇塞,变成了2,560byte。看来这个选项确实把文件变小了N多。
& l/ P% K* |; k* G9 V( t" N( F5.2 在查察连接选项中还有没有什么特别的。发现/align:xx还可以将段大小缩2 |& |3 N3 ~& G
小。通过UltraEdit察看刚才/opt:nowin98编译出来的文件,发现每个段的大小都( p# j' ]) _. j! Y5 U1 \/ F& Q
是4K的整数倍。看来/align:xx还有减小的趋势。试一把再说:添加连接选项:
! p9 Q; V: H; V/align:16(这个大小已经是能够设定的最小的了)。看看结果:1,408Bytes。厉. W" u( B) n2 _3 o/ f7 I/ o# S
害,现在代码更小了。8 c+ U* _! {% S: s: B
5.3 现在回想起来,执行文件大小有数据段,执行代码段等等,如果把这些段都合( w, \0 W+ U+ S: a* p; N
并起来,是不是就会把段之间的冗余有减小了呢?再试试看:添加选项:
* V+ q( w- E& y4 M# S/merge:.data=.text /merge:.rdata=.text。再看看文件大小:1,328bytes。真的$ }. T3 ?4 E& j. E
很不错了。$ w' y* l# U' K4 Y8 V# C+ q" L
$ G) c; W# ^+ ?4 s/ {& a: p
6、刚才的设定确实不错,似乎达到了我们想要的极限了。但是回头想一下,如果6 _- [0 U! ]9 N2 _- L
没有CRT库的话,会不会更小了?实际上确实这样。添加连接选项: /entry:9 [% K6 o0 u$ Z2 F6 s2 u4 F
main,把入口地址直接指向我们的main函数看看。得到592Bytes。
$ ?* U" a& p9 h6 C/ C
6 F" ^" g3 M5 C1 i8 G* `最终我们得到我们最后的大小592Bytes了。我想这也许是我们通过编译器能够编译0 G$ R" C" M( i1 e! f- q
出来的最小的代码了。0 l! d* i" n+ s7 ^ q
0 x N, ^; l) Q4 I. x( G8 Y
结论:
: Y# Q( z4 A2 M" `3 ?# d通过上述的步骤,我们了解了如何修改那些编译连接选项来达到执行文件瘦身的目
+ t- {, s3 A* T' G的。但是,通常来讲,在我们的Release文件当中,并不需要如此小的执行文件。# F: o+ T! E2 r% ? G; `: c
如果想达到瘦身的目的,修改为library:MutiThreaded Dll和添加/opt:nowin98已; z# J, W( q; W" o# l7 g
经是很好的选择了。其他别的选项在编译的时候或多或少的有警告出现,而且,带; S+ |% Q$ @0 M% A9 H) |
有那些编译选项编出来的执行文件也不一定在各个平台上能够适用。5 F/ j+ ?. `1 h6 w
& p2 h0 x$ ^# d3 X另外:如果你的执行文件即使通过了这些设定还是比较大的话,也可以通过一些
9 m1 G( w' U9 |) l& F# vEXE文件压缩工具来进行压缩。比如UPX等等。在此不再细说了。3 \4 Z/ u& @/ ~, { O1 M$ B6 A" e
# U- x3 v( [( U' i/ _! z3 M
以上部分的不足之处,还请多多指正。 |
|