|
|
|
在网上,有好多绿色软件,不仅功能强大,而且软件本身的体积非常小。有的通常5 r; \, P- g0 t8 Q, O
只在几十K左右。那他们是怎么做到把软件做的怎么小的呢?现在我手把手的告诉
) z: v! m G! \; j, H5 O你如何通过修改程序的编译选项来瘦身你的执行文件
9 I: T, M2 q A1 D先看一个最典型的程序: * N% H' L& j9 _2 G( q8 R
#include<stdio.h>
+ W) i5 E% G& Dint main()
% F) o R2 r: ~; D& s n6 g* v, h/ u{4 ~# E6 \! p5 i. \( d& O8 o
printf("Hello,World");
3 M* k, E1 h9 C C0 V return 0;
/ \) }8 `/ ^( ~}3 E) G) O' W. O6 T( M0 a2 @
) b' `/ k& _, n+ w7 O
上面的程序之所以被称之为典型,是因为他有如下的内容:
2 g/ ?7 l k, l+ N5 c1、系统函数调用:printf
0 p- a" m1 G$ S' T! }* c9 _6 z2、有静态数据段
* w, L# y- F! F3 B1 r; Z0 Y; {, l7 V+ Y% j0 x
好,现在把此文件放到VisualStudio6.0中进行编译,看看文件有多大。 A& G& ^3 Y. Z/ @7 o: D
1、用VisualStudio6.0打开HelloWorld.cpp文件,直接按F7。然后点击OK,生成
9 V6 S+ v% R8 y( u6 O U3 y s& |Project文件,然后进行编译。编译完成了以后,看看Debug目录下的执行文件的大
2 K# C. L' j- U9 M小,为172,096Bytes。4 S; O3 e( L+ G
% Y8 N# b" d9 |9 }2、刚才编译的Debug文件,现在修改成Release文件看看。选择Win32 Release,再" c' b b" U1 m& h8 k
编译。察看执行文件大小,现在成了40,960Bytes。看来Debug版本的要比Release
1 N8 f& B$ ~2 G/ B+ N; Q9 X8 p$ I的小。" t$ ^) k; U8 M& {; b; y
/ E7 T6 m6 J$ A1 z2 r3、检查代码优化:发现执行文件的优化是Maximize Speed。那么修改成Minimize
* A* z) j; I4 P P; K( L, KSize看看。重新编译,得到执行文件的大小为:40,960Bytes。看来大小没什么变
' i4 a/ l _$ o0 W/ a化。其实这是由于我们的代码本身太小的缘故,导致即使变化了也看不出来。' s0 D, v4 ^' S' L
" u, N0 @' C9 E7 F4、想想我们程序的main函数是由CRT类库进行引导的。在我们现在的设定当中,由
. R B. L7 j$ _0 Y2 f' S( ?/ P于采取的是系统缺省的编译连接方式(缺省为编译为Single Thread,Static
G3 |0 }& w3 d) Z5 Z4 s8 GLibrary),所以,在我们的执行文件当中,包含了CRT的二进制代码。好,修改编. _# a5 Y; m2 c. Z9 `, t; A6 @
译选项:C/C++ => Category:Code Generation => Use run-time
0 T1 ~: L, v1 C) x" _8 q- D8 Mlibrary:MutiThreaded Dll。编译看看:执行文件大小变成了16,384Bytes。1 ]5 R2 m! \7 X
) g1 X# _0 r- h G5、刚才的设定确实不错,一下子把执行文件大小减小到了16K。现在用UltraEdit5 D6 I+ K7 W2 L, ~: ~. K
看看执行文件都是些什么内容。结果大吃一惊:基本上都是0。看来这个有减小的. Y9 x/ m' F+ A- p- Y
必要了。都知道,执行文件都有自己的代码段,数据段等等,每个段的大小也是采
- R( u: G" F) J/ Y用编译器缺省设定的。好,我们来修改一下段的大小看看:
9 |* s% Q1 `0 P1 e. w ]5.1 连接选项中有一个是/opt:nowin98,意思是将段的大小设定成为Win2000适应
! S, `4 U: F8 s: h+ U, |0 Q的。编译看看:哇塞,变成了2,560byte。看来这个选项确实把文件变小了N多。
& k6 C; E# O I; }. C5.2 在查察连接选项中还有没有什么特别的。发现/align:xx还可以将段大小缩; I2 c+ Q# G; \1 n! }7 n
小。通过UltraEdit察看刚才/opt:nowin98编译出来的文件,发现每个段的大小都
: e8 y" L7 j0 t, Q# ]2 `; i, a是4K的整数倍。看来/align:xx还有减小的趋势。试一把再说:添加连接选项: i0 |" o/ B! G+ W& E5 C* v. D8 M
/align:16(这个大小已经是能够设定的最小的了)。看看结果:1,408Bytes。厉
( { D+ i! H2 h/ Z害,现在代码更小了。) t' d1 _% R# ?% [
5.3 现在回想起来,执行文件大小有数据段,执行代码段等等,如果把这些段都合( ]4 a, l: O, _- T. p0 y3 b, T2 G; k
并起来,是不是就会把段之间的冗余有减小了呢?再试试看:添加选项:
' D8 _1 g( Q0 `& q- t4 M- C+ A& k/merge:.data=.text /merge:.rdata=.text。再看看文件大小:1,328bytes。真的
0 p9 {+ Y, F, o" T很不错了。
8 G5 w: V1 h& s' h; y6 A4 f( ] d# p
. s4 v: q3 c6 T8 ^' V7 v6、刚才的设定确实不错,似乎达到了我们想要的极限了。但是回头想一下,如果5 [1 P1 f( p' \+ [. w! _' n1 Q
没有CRT库的话,会不会更小了?实际上确实这样。添加连接选项: /entry:
# ^, D' f# `5 K) m+ }main,把入口地址直接指向我们的main函数看看。得到592Bytes。# n$ A5 u, n" L7 Z N
5 p) G! r. d+ y9 H9 s最终我们得到我们最后的大小592Bytes了。我想这也许是我们通过编译器能够编译3 G9 O3 Q& K# f# j" @( t$ g
出来的最小的代码了。6 G. T1 |9 k0 R8 ]0 V6 l7 E0 ~/ b
' o$ P( g: v8 o7 @
结论:, X: I$ U N4 s$ N P. Z
通过上述的步骤,我们了解了如何修改那些编译连接选项来达到执行文件瘦身的目
' c% _+ T6 `3 t1 b5 o. Z$ t9 \的。但是,通常来讲,在我们的Release文件当中,并不需要如此小的执行文件。
% ~4 X6 Z% h2 G如果想达到瘦身的目的,修改为library:MutiThreaded Dll和添加/opt:nowin98已
' Q1 u, `- e' B6 O经是很好的选择了。其他别的选项在编译的时候或多或少的有警告出现,而且,带
* i) e0 g3 T5 d+ c. e7 P# f- T有那些编译选项编出来的执行文件也不一定在各个平台上能够适用。- M; M" [$ Z; ?# C6 T
6 n0 g2 _3 a8 t- i! m/ n% D另外:如果你的执行文件即使通过了这些设定还是比较大的话,也可以通过一些( {( j3 q( b) Y5 q1 m
EXE文件压缩工具来进行压缩。比如UPX等等。在此不再细说了。9 y( [! p: E! z6 T/ ]: B7 Q q7 q
8 L8 I1 f7 A' T& [
以上部分的不足之处,还请多多指正。 |
|