|
|
|
在网上,有好多绿色软件,不仅功能强大,而且软件本身的体积非常小。有的通常
! Q1 w0 ^! o" A! q; U) l; z只在几十K左右。那他们是怎么做到把软件做的怎么小的呢?现在我手把手的告诉
) A; w6 p o) y0 U+ k& [0 g8 J你如何通过修改程序的编译选项来瘦身你的执行文件! h9 w) F+ v, H( E) w7 Q8 @) e0 {
先看一个最典型的程序: ' `( M0 v, |6 k# G5 J& K7 y
#include<stdio.h>$ q0 S8 `5 p7 ?
int main()! L' A/ n# J% v# A) X, F% R
{8 K4 I( G/ }' Q, s
printf("Hello,World");+ x4 W6 v$ \7 [: q2 r: Z
return 0; ?- W& J8 Y% H8 i9 A( g
}
( R0 o5 S0 R$ u, Z ^. p% i) |, b5 y a0 M$ n
上面的程序之所以被称之为典型,是因为他有如下的内容:1 N! ~" _& f" t
1、系统函数调用:printf
% r `% h( j: c2、有静态数据段+ v* w- M9 s: r, B/ I3 t( P5 M }
9 D# E9 I3 d1 W% P: o好,现在把此文件放到VisualStudio6.0中进行编译,看看文件有多大。
! ]# J( x+ K1 Y3 {1、用VisualStudio6.0打开HelloWorld.cpp文件,直接按F7。然后点击OK,生成; k% m, y0 \8 E% \1 `9 H
Project文件,然后进行编译。编译完成了以后,看看Debug目录下的执行文件的大' Z( O! b& M% d5 q& h
小,为172,096Bytes。
* K# e3 J5 G2 f+ _' H; @& I7 f' E# ~8 w% ?
2、刚才编译的Debug文件,现在修改成Release文件看看。选择Win32 Release,再& {0 i, @9 F3 v2 x
编译。察看执行文件大小,现在成了40,960Bytes。看来Debug版本的要比Release
! U9 B6 ~4 c' I的小。
1 V( ]5 ]& y/ Z, o8 U3 R' T5 X
5 }" N: X1 q, w# v# l3、检查代码优化:发现执行文件的优化是Maximize Speed。那么修改成Minimize+ D- l, Y0 Z e/ y* w
Size看看。重新编译,得到执行文件的大小为:40,960Bytes。看来大小没什么变* B/ P/ W1 N: @. S. l
化。其实这是由于我们的代码本身太小的缘故,导致即使变化了也看不出来。- E0 x$ Q+ G/ b
) Z8 Z8 v6 b+ k
4、想想我们程序的main函数是由CRT类库进行引导的。在我们现在的设定当中,由
2 T4 H% r& I$ B4 O, p于采取的是系统缺省的编译连接方式(缺省为编译为Single Thread,Static6 `: k! ]2 D# d! C& m: u
Library),所以,在我们的执行文件当中,包含了CRT的二进制代码。好,修改编
' `( s5 {8 W0 k; B) F& P译选项:C/C++ => Category:Code Generation => Use run-time
6 t& Y* L0 h( k1 n6 Klibrary:MutiThreaded Dll。编译看看:执行文件大小变成了16,384Bytes。
, z" G8 d6 H9 h/ G: _$ w
0 r5 e* h1 F. y. o" A$ S5、刚才的设定确实不错,一下子把执行文件大小减小到了16K。现在用UltraEdit8 _ Y. J. @( p& w0 w# S
看看执行文件都是些什么内容。结果大吃一惊:基本上都是0。看来这个有减小的/ k! D/ \9 O' \7 v0 h
必要了。都知道,执行文件都有自己的代码段,数据段等等,每个段的大小也是采
3 ?: y. h5 W# c) U: r. b' s用编译器缺省设定的。好,我们来修改一下段的大小看看:
6 n/ z" V# Z1 }0 ^, n7 e) w6 m5.1 连接选项中有一个是/opt:nowin98,意思是将段的大小设定成为Win2000适应
8 i' l2 l5 U Z的。编译看看:哇塞,变成了2,560byte。看来这个选项确实把文件变小了N多。3 ~: V! {6 t6 L
5.2 在查察连接选项中还有没有什么特别的。发现/align:xx还可以将段大小缩
* L5 {; @1 \/ U0 B& ^ Z; v小。通过UltraEdit察看刚才/opt:nowin98编译出来的文件,发现每个段的大小都
: |0 [6 @" n; |1 X9 u" {是4K的整数倍。看来/align:xx还有减小的趋势。试一把再说:添加连接选项:
0 v8 X" l% h# I6 D( |( }! G7 G/align:16(这个大小已经是能够设定的最小的了)。看看结果:1,408Bytes。厉
- u9 r: A1 T Z9 k( ]+ }( c- X害,现在代码更小了。5 j( J+ I- X9 F% v
5.3 现在回想起来,执行文件大小有数据段,执行代码段等等,如果把这些段都合5 R" h3 g$ T8 C+ R+ j
并起来,是不是就会把段之间的冗余有减小了呢?再试试看:添加选项:
$ E) G0 O( V% P8 S/merge:.data=.text /merge:.rdata=.text。再看看文件大小:1,328bytes。真的
' c5 P( l+ ~) I( t/ }; r$ a! W% V很不错了。
, u I- K8 C) w3 i) |! T7 E! F8 M* [( g$ d
6、刚才的设定确实不错,似乎达到了我们想要的极限了。但是回头想一下,如果
, O. C' t( x8 U没有CRT库的话,会不会更小了?实际上确实这样。添加连接选项: /entry:0 ` r" A- n9 |# v. h
main,把入口地址直接指向我们的main函数看看。得到592Bytes。" I# j+ P8 X' [. l( t
. r/ d* B5 D h最终我们得到我们最后的大小592Bytes了。我想这也许是我们通过编译器能够编译1 S9 ?7 c4 N* V$ s" L: j; w; p
出来的最小的代码了。
( e6 A( f( x7 u6 g# R7 o4 H4 T) F
+ v! k- ^! I# n* r! G8 v: s结论:
! K2 }+ I9 z- ~6 P通过上述的步骤,我们了解了如何修改那些编译连接选项来达到执行文件瘦身的目
3 I8 i0 z4 u0 T( {0 v) E的。但是,通常来讲,在我们的Release文件当中,并不需要如此小的执行文件。; p6 l# w% b2 i
如果想达到瘦身的目的,修改为library:MutiThreaded Dll和添加/opt:nowin98已 J* ?1 D: d% {8 _) H
经是很好的选择了。其他别的选项在编译的时候或多或少的有警告出现,而且,带( @$ P8 _1 c/ C4 y+ _( ^6 L f' @) i
有那些编译选项编出来的执行文件也不一定在各个平台上能够适用。) p% f* K3 E+ ~& d* x T
- G0 l1 l7 F9 s$ T$ _2 I' S
另外:如果你的执行文件即使通过了这些设定还是比较大的话,也可以通过一些
6 d$ G1 v1 _" p& ^5 v0 REXE文件压缩工具来进行压缩。比如UPX等等。在此不再细说了。
7 g: B7 k: O; g
0 ?, |) S. a; q( }以上部分的不足之处,还请多多指正。 |
|