|
|
|
在网上,有好多绿色软件,不仅功能强大,而且软件本身的体积非常小。有的通常
" r7 F6 O3 w" d2 C' c k! P: z只在几十K左右。那他们是怎么做到把软件做的怎么小的呢?现在我手把手的告诉
, [$ o" m# k, @% C你如何通过修改程序的编译选项来瘦身你的执行文件
9 e7 T3 v4 y" P' p% y6 y% b先看一个最典型的程序:
4 R4 D( K5 U4 P7 i9 G#include<stdio.h># x% b$ k# A- j4 h; ?* P& U
int main()1 N% B1 K' M3 o1 m! j. v
{. a- K( q7 M/ R+ P) Z7 Z
printf("Hello,World");
( n5 Y& R8 b0 y0 a( ^ return 0;
# ]8 J9 G W) \3 H9 ?* V8 \}
' o1 W5 A% n* X R! z+ z
7 z$ C/ i1 x# U/ R4 u7 t/ {, I上面的程序之所以被称之为典型,是因为他有如下的内容:5 @( [* _+ ~% u% A% ?* c
1、系统函数调用:printf% T% W% G& V$ q+ c
2、有静态数据段' c1 N; X% `3 Q% y8 B O% ~
: {9 x z: M, F, Y5 W8 T! W( o% V好,现在把此文件放到VisualStudio6.0中进行编译,看看文件有多大。
/ J6 U( [1 H' d9 v' x( z1、用VisualStudio6.0打开HelloWorld.cpp文件,直接按F7。然后点击OK,生成( E/ P! {- _0 m% Q5 }1 B4 b# f
Project文件,然后进行编译。编译完成了以后,看看Debug目录下的执行文件的大
3 ~4 N2 B8 S: w! f小,为172,096Bytes。3 N, H0 l O: b
0 i$ q* p* r5 F2、刚才编译的Debug文件,现在修改成Release文件看看。选择Win32 Release,再
# a6 v* P3 H! P C+ f& H编译。察看执行文件大小,现在成了40,960Bytes。看来Debug版本的要比Release
& B* k5 Q j' E# B的小。9 ^5 z- g) A, _: @% `9 h
, N$ Z. t$ u2 U1 s- K; V3、检查代码优化:发现执行文件的优化是Maximize Speed。那么修改成Minimize1 J. f8 M: A$ B. q, M! o
Size看看。重新编译,得到执行文件的大小为:40,960Bytes。看来大小没什么变
* V$ ^+ B8 g6 m/ H化。其实这是由于我们的代码本身太小的缘故,导致即使变化了也看不出来。
3 E" V+ D/ i ]/ N" {: m# L+ N: w$ v6 C
& @) ]0 Y8 q$ d2 W9 P7 d7 z4、想想我们程序的main函数是由CRT类库进行引导的。在我们现在的设定当中,由
) |7 E. }% @2 {& J于采取的是系统缺省的编译连接方式(缺省为编译为Single Thread,Static
8 k- [ F2 v' E z! m: V1 b* @5 gLibrary),所以,在我们的执行文件当中,包含了CRT的二进制代码。好,修改编! ~& ], x) q' f; d0 H% U" n
译选项:C/C++ => Category:Code Generation => Use run-time
6 t( k# X# Y; Q; ] |; {1 Zlibrary:MutiThreaded Dll。编译看看:执行文件大小变成了16,384Bytes。
7 U T- k3 @; U* M( f R$ o
2 [( W$ m! ]( _$ O9 F! F, }5、刚才的设定确实不错,一下子把执行文件大小减小到了16K。现在用UltraEdit
- H' O. I& R5 L: l+ q6 w0 {看看执行文件都是些什么内容。结果大吃一惊:基本上都是0。看来这个有减小的1 j4 l) Y7 b6 ^( t
必要了。都知道,执行文件都有自己的代码段,数据段等等,每个段的大小也是采- m8 o' n ]8 T/ c! I
用编译器缺省设定的。好,我们来修改一下段的大小看看:8 m$ ^% l! r3 v8 S
5.1 连接选项中有一个是/opt:nowin98,意思是将段的大小设定成为Win2000适应
& s8 y, L- `; ^' r的。编译看看:哇塞,变成了2,560byte。看来这个选项确实把文件变小了N多。8 |7 v0 i# J8 x" E& z
5.2 在查察连接选项中还有没有什么特别的。发现/align:xx还可以将段大小缩
9 W7 m1 P# G, F/ M M小。通过UltraEdit察看刚才/opt:nowin98编译出来的文件,发现每个段的大小都" Y+ n* z: I2 L5 ]9 [
是4K的整数倍。看来/align:xx还有减小的趋势。试一把再说:添加连接选项:
% ~6 S' k2 L9 }3 h" A' h2 m7 G/align:16(这个大小已经是能够设定的最小的了)。看看结果:1,408Bytes。厉
$ h4 Y# u1 N& ?% y害,现在代码更小了。9 H2 Q- U x6 J( m L- g7 o
5.3 现在回想起来,执行文件大小有数据段,执行代码段等等,如果把这些段都合
2 {' N% x2 i) l. m并起来,是不是就会把段之间的冗余有减小了呢?再试试看:添加选项:
) F0 B. S3 Z$ H u% O# c/merge:.data=.text /merge:.rdata=.text。再看看文件大小:1,328bytes。真的
, p+ I3 d6 q/ l/ t- A- u [4 S" p很不错了。+ A% i# {* }4 K( a& c
$ K4 a: |$ ^1 j$ u4 T6、刚才的设定确实不错,似乎达到了我们想要的极限了。但是回头想一下,如果- N2 ^- h: s8 n1 h6 o5 `
没有CRT库的话,会不会更小了?实际上确实这样。添加连接选项: /entry:
1 Z+ S/ j# H i* k( C. }main,把入口地址直接指向我们的main函数看看。得到592Bytes。
: B9 \, q- m, a2 h# ^7 x* X9 F+ W8 i" G+ Z6 R9 g
最终我们得到我们最后的大小592Bytes了。我想这也许是我们通过编译器能够编译
+ y: M3 a: F8 u4 [0 ?8 B出来的最小的代码了。
8 M, j9 j0 X) O* e3 b* a# `$ S% S1 c& b
结论:
! d/ {: R. N' L通过上述的步骤,我们了解了如何修改那些编译连接选项来达到执行文件瘦身的目
5 F+ X! \* L& n; B( K的。但是,通常来讲,在我们的Release文件当中,并不需要如此小的执行文件。7 j" z6 f: V; z+ Z2 s0 |) t$ L0 z
如果想达到瘦身的目的,修改为library:MutiThreaded Dll和添加/opt:nowin98已
% ~' x9 \3 A7 S7 j! ?% D* z7 ^% s经是很好的选择了。其他别的选项在编译的时候或多或少的有警告出现,而且,带
. J5 R8 O8 e1 s; e5 C# i有那些编译选项编出来的执行文件也不一定在各个平台上能够适用。
* Y0 f K+ o' E" `1 _" |: U: [8 w6 I0 I5 Q, n6 r
另外:如果你的执行文件即使通过了这些设定还是比较大的话,也可以通过一些4 w1 V0 c; @2 R2 O/ T+ _% I; a
EXE文件压缩工具来进行压缩。比如UPX等等。在此不再细说了。. D t. `! @- \+ r+ N# H
& K) {# C- _! w4 v' R! `以上部分的不足之处,还请多多指正。 |
|