|
|
|
在网上,有好多绿色软件,不仅功能强大,而且软件本身的体积非常小。有的通常
+ t1 h. W$ h; C7 s7 |- P( G; X只在几十K左右。那他们是怎么做到把软件做的怎么小的呢?现在我手把手的告诉/ n$ K6 Q! G) D
你如何通过修改程序的编译选项来瘦身你的执行文件5 O6 f1 B8 s4 [* v- Z
先看一个最典型的程序:
3 c. D# }4 C- f0 f1 T; F* X6 u+ j: T#include<stdio.h>1 `: T: U$ i; V6 p; m1 V
int main()/ c/ n8 `% D% C% S; Y
{, C& W% e2 i+ e8 V9 g l
printf("Hello,World");
6 L2 u3 a; t7 m! e return 0;- K/ y( J- J" S) s2 g+ O- ^
}8 W2 w q. |+ A. N2 S0 l F" c
0 J$ a1 o; f2 X
上面的程序之所以被称之为典型,是因为他有如下的内容: K( j- o* A' w' l- n6 a* f
1、系统函数调用:printf
5 s4 o& k9 i$ D* j6 r, K; C2、有静态数据段 x4 p/ k+ [6 n8 ?1 t
$ L* l4 o2 t2 L+ P$ k好,现在把此文件放到VisualStudio6.0中进行编译,看看文件有多大。3 i$ v/ v6 m& Q( X
1、用VisualStudio6.0打开HelloWorld.cpp文件,直接按F7。然后点击OK,生成
e- Y3 ?& x' @6 G0 l1 AProject文件,然后进行编译。编译完成了以后,看看Debug目录下的执行文件的大
b3 y) b+ f' A* H: K小,为172,096Bytes。
7 M8 ~5 T* M0 w8 K) e. O1 j/ t$ l) c, X
2、刚才编译的Debug文件,现在修改成Release文件看看。选择Win32 Release,再3 O6 p8 [ Z8 @
编译。察看执行文件大小,现在成了40,960Bytes。看来Debug版本的要比Release
& A* m, _9 b+ S7 n0 s的小。
4 S. s7 Y m5 b6 n1 f+ v1 P+ p! h y% `2 H1 G- @; d _1 J7 {
3、检查代码优化:发现执行文件的优化是Maximize Speed。那么修改成Minimize7 f/ \3 }% L$ m- c# ~
Size看看。重新编译,得到执行文件的大小为:40,960Bytes。看来大小没什么变2 \5 |) p9 _2 M* D; L+ s
化。其实这是由于我们的代码本身太小的缘故,导致即使变化了也看不出来。
. a3 H0 f( z) {: x! v1 \. e' L% [+ r7 x5 o0 U% E% f
4、想想我们程序的main函数是由CRT类库进行引导的。在我们现在的设定当中,由$ Y* c1 X4 Q# a) k" Q+ _# @( ^
于采取的是系统缺省的编译连接方式(缺省为编译为Single Thread,Static7 N ^/ n l, W B9 X4 c0 ~- @
Library),所以,在我们的执行文件当中,包含了CRT的二进制代码。好,修改编4 \& Q. Y( J! T0 Y2 u1 x
译选项:C/C++ => Category:Code Generation => Use run-time1 W4 d' c5 \. q: ~; I B1 w
library:MutiThreaded Dll。编译看看:执行文件大小变成了16,384Bytes。
& G7 B3 G: Q3 y
2 z) Z2 o3 L, @. @1 Q5、刚才的设定确实不错,一下子把执行文件大小减小到了16K。现在用UltraEdit
: R8 M5 I: O! A1 y& Y看看执行文件都是些什么内容。结果大吃一惊:基本上都是0。看来这个有减小的6 R" T8 i8 \. O3 T3 ` Z0 }4 c6 D
必要了。都知道,执行文件都有自己的代码段,数据段等等,每个段的大小也是采
! G8 R% c5 z2 ?' P( s用编译器缺省设定的。好,我们来修改一下段的大小看看:
P: V& n* ?7 s5.1 连接选项中有一个是/opt:nowin98,意思是将段的大小设定成为Win2000适应" y1 @2 ^) q% f+ M4 @6 I) X
的。编译看看:哇塞,变成了2,560byte。看来这个选项确实把文件变小了N多。
1 i7 E; n& r" z) |3 X5.2 在查察连接选项中还有没有什么特别的。发现/align:xx还可以将段大小缩( s5 i5 s* U3 k% s8 h
小。通过UltraEdit察看刚才/opt:nowin98编译出来的文件,发现每个段的大小都
) c8 v! ?& y8 {是4K的整数倍。看来/align:xx还有减小的趋势。试一把再说:添加连接选项:
, ~1 H+ e0 r1 _7 F; l! |4 c) ~5 b. {/align:16(这个大小已经是能够设定的最小的了)。看看结果:1,408Bytes。厉
1 x$ y4 j5 w4 A) S |' F害,现在代码更小了。
9 [& X% U$ b) J L2 O5.3 现在回想起来,执行文件大小有数据段,执行代码段等等,如果把这些段都合# N: y9 u1 _( c( d8 G( e
并起来,是不是就会把段之间的冗余有减小了呢?再试试看:添加选项:
4 s$ M" @/ {6 v' k6 m/merge:.data=.text /merge:.rdata=.text。再看看文件大小:1,328bytes。真的
# q* X8 ?% k+ {3 }5 R很不错了。% u0 {+ e: X7 o( }3 [
9 g) M3 j4 l0 q) v
6、刚才的设定确实不错,似乎达到了我们想要的极限了。但是回头想一下,如果
* ^, z5 D% j2 C1 F0 H. ~2 {没有CRT库的话,会不会更小了?实际上确实这样。添加连接选项: /entry:
- \( C- s( b3 ]/ w# vmain,把入口地址直接指向我们的main函数看看。得到592Bytes。
) m) i* S* R+ B/ _/ b1 |
4 t8 N1 [3 y' j# F% e. q2 x! M最终我们得到我们最后的大小592Bytes了。我想这也许是我们通过编译器能够编译
% L. _: ?# o/ c3 y0 j- j7 l. P4 K出来的最小的代码了。1 ?. Z4 w0 X: l$ T. x
8 S* ~( \3 Y7 F& [# b结论:! |; z) h3 c" K2 v2 X* ]% F) Z
通过上述的步骤,我们了解了如何修改那些编译连接选项来达到执行文件瘦身的目6 x1 f% n! q" D K% }* s- P& A
的。但是,通常来讲,在我们的Release文件当中,并不需要如此小的执行文件。
* g& R8 l2 s( F9 e. B" y8 i如果想达到瘦身的目的,修改为library:MutiThreaded Dll和添加/opt:nowin98已( ~4 N4 P( @6 s1 \8 H H4 u S1 v
经是很好的选择了。其他别的选项在编译的时候或多或少的有警告出现,而且,带, \% K& Z0 f1 E* b7 p
有那些编译选项编出来的执行文件也不一定在各个平台上能够适用。
- [/ y: T, s1 S: t W" O
) C l$ l( W7 g+ Q8 a另外:如果你的执行文件即使通过了这些设定还是比较大的话,也可以通过一些+ ], m0 u2 \# t' R/ l( K0 ?8 B7 V
EXE文件压缩工具来进行压缩。比如UPX等等。在此不再细说了。( q( k4 R" O5 i Z; R
# f" D C2 l! y
以上部分的不足之处,还请多多指正。 |
|