|
|
|
在网上,有好多绿色软件,不仅功能强大,而且软件本身的体积非常小。有的通常
$ L8 |% _6 M" J只在几十K左右。那他们是怎么做到把软件做的怎么小的呢?现在我手把手的告诉8 o. ~# \' \4 _5 x/ _! G# _/ l+ a/ D* |
你如何通过修改程序的编译选项来瘦身你的执行文件) `6 u# K1 a+ @) h- O0 h
先看一个最典型的程序:
/ s% E3 ?# \/ _4 A* u#include<stdio.h>; W- R, }: m% W
int main()1 W* j+ k) ^/ }# U
{! U7 y3 b: o# p% l5 c- l
printf("Hello,World");
2 q0 \8 N- `" R' O# W0 ]' ^ return 0;
) U0 U8 Z$ Z$ G/ Z7 A# O8 n}
0 r% Y" K: d- b* A
1 w+ c W; `) m0 T3 ^7 u0 @上面的程序之所以被称之为典型,是因为他有如下的内容:/ {$ k$ W( Y9 i! [3 f E) ~* ]
1、系统函数调用:printf
9 L% l3 i' ~& D; F( |9 {; P2、有静态数据段: Z a* R4 G# j5 |6 o
! m% ^; J9 y- I
好,现在把此文件放到VisualStudio6.0中进行编译,看看文件有多大。
' H/ m$ z5 X0 `$ A4 K4 h+ u4 P% U: q1、用VisualStudio6.0打开HelloWorld.cpp文件,直接按F7。然后点击OK,生成! b8 p1 |" u% O0 Z- f( u( Z
Project文件,然后进行编译。编译完成了以后,看看Debug目录下的执行文件的大$ ]& g% ]9 R$ P. w3 O6 A; N% k
小,为172,096Bytes。
* H; L/ \4 Q% b, I+ I7 E3 P1 Z- u3 I7 m, K1 T* w& {8 d
2、刚才编译的Debug文件,现在修改成Release文件看看。选择Win32 Release,再0 l% S& J+ V1 a, ]# }. S% K* W
编译。察看执行文件大小,现在成了40,960Bytes。看来Debug版本的要比Release- r) H1 \8 M( f; s. M
的小。2 s \6 F; t/ @3 \6 _- V$ i
1 }$ V. m1 f( |# J/ e
3、检查代码优化:发现执行文件的优化是Maximize Speed。那么修改成Minimize' u3 b# e& t7 Q. s7 ]
Size看看。重新编译,得到执行文件的大小为:40,960Bytes。看来大小没什么变
2 y2 x K3 O' @& P) G0 F. P7 ?化。其实这是由于我们的代码本身太小的缘故,导致即使变化了也看不出来。* v; X" X l! _# O/ Y+ t+ r
; H& k) [6 I# @
4、想想我们程序的main函数是由CRT类库进行引导的。在我们现在的设定当中,由
' O: L" F8 d9 r8 @于采取的是系统缺省的编译连接方式(缺省为编译为Single Thread,Static( g) L4 v; n3 J% h) | N
Library),所以,在我们的执行文件当中,包含了CRT的二进制代码。好,修改编" ]" d9 ~# |* l% A7 ]
译选项:C/C++ => Category:Code Generation => Use run-time
8 L& F, q2 v; V3 y! R- l3 m5 m+ W" D: llibrary:MutiThreaded Dll。编译看看:执行文件大小变成了16,384Bytes。0 p; ?: x% g5 k" ]* @" s
: D/ w- Q% E' J) N$ ]5 H5、刚才的设定确实不错,一下子把执行文件大小减小到了16K。现在用UltraEdit5 m" F( Y% ]( {1 D2 L; G
看看执行文件都是些什么内容。结果大吃一惊:基本上都是0。看来这个有减小的
5 p7 N2 p! A3 L' _( M' r* i: X必要了。都知道,执行文件都有自己的代码段,数据段等等,每个段的大小也是采
" l# R( N- r9 ]0 ] e- w, q用编译器缺省设定的。好,我们来修改一下段的大小看看:0 ]- @8 Z0 N' h: {: o" x0 T* H
5.1 连接选项中有一个是/opt:nowin98,意思是将段的大小设定成为Win2000适应
% K, l, G/ b- o! A# U的。编译看看:哇塞,变成了2,560byte。看来这个选项确实把文件变小了N多。6 X& V# b+ c9 \, v
5.2 在查察连接选项中还有没有什么特别的。发现/align:xx还可以将段大小缩
r0 f! A8 k9 ^! p @$ ~ K' S小。通过UltraEdit察看刚才/opt:nowin98编译出来的文件,发现每个段的大小都! H0 N& {3 F: f; J9 g1 N; S; U
是4K的整数倍。看来/align:xx还有减小的趋势。试一把再说:添加连接选项:
" V+ C' u8 H: Z; I/align:16(这个大小已经是能够设定的最小的了)。看看结果:1,408Bytes。厉
2 t) Y$ S4 d( C. R3 o2 p" P& A害,现在代码更小了。
: L' P: C, t( I; N5.3 现在回想起来,执行文件大小有数据段,执行代码段等等,如果把这些段都合, e& C& k6 q* V* F, M5 H& p
并起来,是不是就会把段之间的冗余有减小了呢?再试试看:添加选项:
! Y( r8 H$ Q. Y/merge:.data=.text /merge:.rdata=.text。再看看文件大小:1,328bytes。真的- ?& B) K* ?9 b
很不错了。4 b; t% P) H8 X" p% `
- {1 P" k7 K' A" f' e: q6、刚才的设定确实不错,似乎达到了我们想要的极限了。但是回头想一下,如果2 O. i; c' }/ W0 @( `* n3 f- _
没有CRT库的话,会不会更小了?实际上确实这样。添加连接选项: /entry:2 J7 B5 h' L2 V5 l- ?
main,把入口地址直接指向我们的main函数看看。得到592Bytes。4 _: w0 ~0 |6 d3 C7 A j
, S5 h0 ~9 z& h0 m. m最终我们得到我们最后的大小592Bytes了。我想这也许是我们通过编译器能够编译2 ?' M- ~- w4 x) p/ e) L
出来的最小的代码了。
4 t8 O3 h4 p/ o/ _& e2 ?( C: H* f5 O& M0 O
结论:
3 l# w5 C7 _" c通过上述的步骤,我们了解了如何修改那些编译连接选项来达到执行文件瘦身的目, Y( y! S) x( a) g( r$ z
的。但是,通常来讲,在我们的Release文件当中,并不需要如此小的执行文件。3 {" w7 Y, N4 S# m
如果想达到瘦身的目的,修改为library:MutiThreaded Dll和添加/opt:nowin98已
* S w& E+ @8 \6 j: x3 Q. ~6 f经是很好的选择了。其他别的选项在编译的时候或多或少的有警告出现,而且,带; v/ }) w1 d9 s/ {1 `
有那些编译选项编出来的执行文件也不一定在各个平台上能够适用。
5 Y9 A; f) ^0 u; @; J
1 W' `+ |" R Z7 s0 M$ o另外:如果你的执行文件即使通过了这些设定还是比较大的话,也可以通过一些1 v- q3 k+ a2 D$ A! E+ H
EXE文件压缩工具来进行压缩。比如UPX等等。在此不再细说了。
' Z( m; h1 G* p" ~7 i
+ @, L8 N' x1 R/ o, Z以上部分的不足之处,还请多多指正。 |
|