|
|
|
在网上,有好多绿色软件,不仅功能强大,而且软件本身的体积非常小。有的通常
# |3 v; O$ g X! i3 h3 S只在几十K左右。那他们是怎么做到把软件做的怎么小的呢?现在我手把手的告诉# ]' ^% M6 \! Q$ r; D
你如何通过修改程序的编译选项来瘦身你的执行文件
% n" B7 H0 y$ s$ q先看一个最典型的程序: / d2 `' J" ^5 _1 F
#include<stdio.h>
6 X0 E" o4 w& Fint main()
$ l! C7 g& o% b{+ k1 m j$ j# r' i* S' l
printf("Hello,World");8 Y( P% Z3 H" K4 X# ]$ L' Q
return 0;) |7 U/ E4 g. m
}) {# ~2 j$ B* n' [% b( n
$ n# D. T e% w8 V
上面的程序之所以被称之为典型,是因为他有如下的内容:
* V Q4 U) m( ~9 r$ `7 o1、系统函数调用:printf
9 V8 `. L6 l. [$ G' y1 H% ]2、有静态数据段
4 l ~) v1 l, V
) v- m6 o( F) H好,现在把此文件放到VisualStudio6.0中进行编译,看看文件有多大。" \4 e9 A( M2 ]# a4 V
1、用VisualStudio6.0打开HelloWorld.cpp文件,直接按F7。然后点击OK,生成" y' {/ f7 z; N M
Project文件,然后进行编译。编译完成了以后,看看Debug目录下的执行文件的大/ J( e! S& W$ d9 N J
小,为172,096Bytes。+ _$ d+ l) Y# f
2 n/ x. {7 c6 N. M& D2 q: b! v
2、刚才编译的Debug文件,现在修改成Release文件看看。选择Win32 Release,再5 ~( B; p \ M) K( M' R7 e- `+ D
编译。察看执行文件大小,现在成了40,960Bytes。看来Debug版本的要比Release# e. [9 v. i, G! K* `; M, q3 d
的小。
$ k3 J% P' r7 |$ D6 X: O3 P$ B5 a T
3、检查代码优化:发现执行文件的优化是Maximize Speed。那么修改成Minimize
0 x( D* v4 V# D+ a5 W5 ySize看看。重新编译,得到执行文件的大小为:40,960Bytes。看来大小没什么变
" z" s- S6 e, f( d+ ?化。其实这是由于我们的代码本身太小的缘故,导致即使变化了也看不出来。
) P+ O1 r4 h, b" F" A5 B* D
( q: H% X! ]! |4、想想我们程序的main函数是由CRT类库进行引导的。在我们现在的设定当中,由- D0 r# y, J/ ~/ E1 l) J$ c. Z
于采取的是系统缺省的编译连接方式(缺省为编译为Single Thread,Static2 q) V7 Q4 |: [6 h' `8 A( C1 c
Library),所以,在我们的执行文件当中,包含了CRT的二进制代码。好,修改编
& x; Y3 M; C. @; s译选项:C/C++ => Category:Code Generation => Use run-time
+ Z- i6 R u) K |( e( A# Llibrary:MutiThreaded Dll。编译看看:执行文件大小变成了16,384Bytes。$ e% @5 j5 n7 D! b
% q5 j1 [ D& |
5、刚才的设定确实不错,一下子把执行文件大小减小到了16K。现在用UltraEdit
0 P6 x6 `5 @ ^# Y看看执行文件都是些什么内容。结果大吃一惊:基本上都是0。看来这个有减小的 ]0 u% O, @9 J# L
必要了。都知道,执行文件都有自己的代码段,数据段等等,每个段的大小也是采
; w( z' c# N0 W- {# X/ v7 j用编译器缺省设定的。好,我们来修改一下段的大小看看:
5 a0 a" ~1 `5 q& H! A; `' Y5.1 连接选项中有一个是/opt:nowin98,意思是将段的大小设定成为Win2000适应
6 a' D a- i/ N- j6 F s+ O( Z的。编译看看:哇塞,变成了2,560byte。看来这个选项确实把文件变小了N多。
% I% Q; E' D9 W4 \" B" r1 N, g5.2 在查察连接选项中还有没有什么特别的。发现/align:xx还可以将段大小缩
' o7 M9 X& c- _2 y+ H" l; Y小。通过UltraEdit察看刚才/opt:nowin98编译出来的文件,发现每个段的大小都$ q0 C6 l. f- h' h" E5 H6 Q2 R1 U& \
是4K的整数倍。看来/align:xx还有减小的趋势。试一把再说:添加连接选项:: [, @; C8 Q7 n% q' _7 p& E8 V
/align:16(这个大小已经是能够设定的最小的了)。看看结果:1,408Bytes。厉: y& F7 A& l" p8 @0 @/ U
害,现在代码更小了。
8 i' v5 L+ M |! g5 [. S/ z& y5.3 现在回想起来,执行文件大小有数据段,执行代码段等等,如果把这些段都合6 a: E- A! A" h8 X; {$ `
并起来,是不是就会把段之间的冗余有减小了呢?再试试看:添加选项:4 y/ e5 S/ w1 Z" c4 r
/merge:.data=.text /merge:.rdata=.text。再看看文件大小:1,328bytes。真的
! l& \, Q$ w) c4 F/ W D2 [ L很不错了。7 S9 o+ E, u7 X( r W5 D
" l/ r+ u" X8 C5 ~3 x4 T9 k* A7 A3 \
6、刚才的设定确实不错,似乎达到了我们想要的极限了。但是回头想一下,如果( h$ Q* s8 c% M/ i2 y( a- u
没有CRT库的话,会不会更小了?实际上确实这样。添加连接选项: /entry:/ L7 A6 Q' S: k7 h0 [' R) F7 \; W
main,把入口地址直接指向我们的main函数看看。得到592Bytes。
; s+ T3 D* E7 H1 K, Z' n- K; l/ d4 [" z' `3 S9 g
最终我们得到我们最后的大小592Bytes了。我想这也许是我们通过编译器能够编译
/ a6 s0 m. n1 V: F2 G出来的最小的代码了。4 G5 ~3 D9 [) G: A# b
( Y* @2 ]0 R) M6 t% w
结论:
, n7 ]' A' ?1 S) k3 {通过上述的步骤,我们了解了如何修改那些编译连接选项来达到执行文件瘦身的目" w4 Z% t2 K: ~) {! U
的。但是,通常来讲,在我们的Release文件当中,并不需要如此小的执行文件。: M8 z! i1 W; k. }6 c( P
如果想达到瘦身的目的,修改为library:MutiThreaded Dll和添加/opt:nowin98已
, k& s' N2 W4 {: }' v5 e. p经是很好的选择了。其他别的选项在编译的时候或多或少的有警告出现,而且,带
& H A; Z1 W+ g2 l' R" i有那些编译选项编出来的执行文件也不一定在各个平台上能够适用。
& `- A, i( P9 a; R; @* @/ L4 \! w
2 O. Z( O- A$ N. t& n2 N2 b$ T另外:如果你的执行文件即使通过了这些设定还是比较大的话,也可以通过一些
( g5 M3 u0 _( R7 lEXE文件压缩工具来进行压缩。比如UPX等等。在此不再细说了。3 @! v6 [4 ]8 H4 a+ ?4 F
$ D" O8 d- f+ H9 s4 v/ W以上部分的不足之处,还请多多指正。 |
|