|
|
|
在网上,有好多绿色软件,不仅功能强大,而且软件本身的体积非常小。有的通常( r. v3 ~9 s/ G; f3 s
只在几十K左右。那他们是怎么做到把软件做的怎么小的呢?现在我手把手的告诉
* y8 J; J, K8 X# V2 D你如何通过修改程序的编译选项来瘦身你的执行文件1 p% D; m) ^6 Y+ h2 `
先看一个最典型的程序:
5 T' l0 U; \! Y0 J, I1 o#include<stdio.h>/ N! F7 k/ s' o- P2 k
int main()
% L7 H- q$ W3 T0 L{5 [, A# d' }& G* O
printf("Hello,World");+ M3 h( T& @6 a3 ?, p/ u4 D3 {( Z
return 0;/ V. @0 n) r) O4 Q/ f) F
}
9 j9 r" C( {- N' ^% \9 Y
& e/ {, }& k* s; S上面的程序之所以被称之为典型,是因为他有如下的内容:6 o/ j4 J4 m% j7 o7 Y) m. e* s2 O
1、系统函数调用:printf
S w$ P, [' }5 e7 t2、有静态数据段
& O# F7 F/ m& a" F) s& Z
7 H U) l" s* a% F* \0 b2 U好,现在把此文件放到VisualStudio6.0中进行编译,看看文件有多大。
# |% g% [# V3 G2 X* \9 _! P1、用VisualStudio6.0打开HelloWorld.cpp文件,直接按F7。然后点击OK,生成- {' K7 t% a4 M# n" d4 l% L
Project文件,然后进行编译。编译完成了以后,看看Debug目录下的执行文件的大! }, e# o3 _3 ]0 K9 E8 d% x
小,为172,096Bytes。+ ^7 r0 ~( _: D( e
" S, Y X/ c. w
2、刚才编译的Debug文件,现在修改成Release文件看看。选择Win32 Release,再0 C8 h7 y0 u4 Q9 j/ l" w
编译。察看执行文件大小,现在成了40,960Bytes。看来Debug版本的要比Release# H2 Y, U5 J- r; y) l) D
的小。
3 n! S% B- @2 G _' j- p- ?, B* Y* k3 W* d$ [
3、检查代码优化:发现执行文件的优化是Maximize Speed。那么修改成Minimize
; H) F5 N! N& E6 V& w2 ]Size看看。重新编译,得到执行文件的大小为:40,960Bytes。看来大小没什么变5 O0 L; z5 J% S5 j
化。其实这是由于我们的代码本身太小的缘故,导致即使变化了也看不出来。
% [: k' R; q* [& }
( K( z0 _: Y l! x4、想想我们程序的main函数是由CRT类库进行引导的。在我们现在的设定当中,由
; c, B0 w6 `% U& Q3 q+ |5 h于采取的是系统缺省的编译连接方式(缺省为编译为Single Thread,Static0 s+ b" V6 A2 [5 C% x
Library),所以,在我们的执行文件当中,包含了CRT的二进制代码。好,修改编
H; k8 {; y( ^% i# T0 _: G译选项:C/C++ => Category:Code Generation => Use run-time
2 Y/ X6 F1 j; A" C _library:MutiThreaded Dll。编译看看:执行文件大小变成了16,384Bytes。' A& ^% |! R8 i5 X
) e! W/ F8 ~2 t' m) }) ` J
5、刚才的设定确实不错,一下子把执行文件大小减小到了16K。现在用UltraEdit
4 i8 p( r# T+ D1 r看看执行文件都是些什么内容。结果大吃一惊:基本上都是0。看来这个有减小的 X( [9 m/ K0 T4 z
必要了。都知道,执行文件都有自己的代码段,数据段等等,每个段的大小也是采) M; x% F, H+ N" q( v* ` E( n
用编译器缺省设定的。好,我们来修改一下段的大小看看:
, L+ `: C8 D0 {& }5.1 连接选项中有一个是/opt:nowin98,意思是将段的大小设定成为Win2000适应4 D% z0 O; m: B$ f9 l& F& F
的。编译看看:哇塞,变成了2,560byte。看来这个选项确实把文件变小了N多。
) f* E3 ~! O, b+ w/ Q* l K$ S5.2 在查察连接选项中还有没有什么特别的。发现/align:xx还可以将段大小缩8 q( P7 ^" c# ^/ `2 x1 K
小。通过UltraEdit察看刚才/opt:nowin98编译出来的文件,发现每个段的大小都
9 O2 V" d( g" G) g9 a是4K的整数倍。看来/align:xx还有减小的趋势。试一把再说:添加连接选项:$ y' ?+ y* [% y6 b
/align:16(这个大小已经是能够设定的最小的了)。看看结果:1,408Bytes。厉) h3 E( a I# H4 @7 E& j0 R
害,现在代码更小了。
# f1 l4 q5 d- G u8 f5 {5.3 现在回想起来,执行文件大小有数据段,执行代码段等等,如果把这些段都合
4 X+ K7 Z# C6 G; `( W2 } w/ g并起来,是不是就会把段之间的冗余有减小了呢?再试试看:添加选项:
; z) d$ M2 R* w" ^" J/merge:.data=.text /merge:.rdata=.text。再看看文件大小:1,328bytes。真的
A9 Z7 P6 Z* G* |$ V4 e很不错了。
6 G% Q) o" p1 R: p9 f3 L' F' ^! D; t; C6 @' A' ]
6、刚才的设定确实不错,似乎达到了我们想要的极限了。但是回头想一下,如果0 j2 H; b3 z0 p$ b) N; `9 x* U7 M
没有CRT库的话,会不会更小了?实际上确实这样。添加连接选项: /entry:
) U% ~9 y0 V' R% W0 k, Xmain,把入口地址直接指向我们的main函数看看。得到592Bytes。7 H. h }9 E) W7 z: Y! z/ e7 c
1 C) q4 e) B7 p# m
最终我们得到我们最后的大小592Bytes了。我想这也许是我们通过编译器能够编译
( ]5 z0 O$ G, p: }8 g出来的最小的代码了。
P) n6 V1 H/ |0 ^
8 I/ Z4 y2 A8 b2 I7 w结论:
! u( R( a* `" @0 S5 x2 H0 H通过上述的步骤,我们了解了如何修改那些编译连接选项来达到执行文件瘦身的目
8 R4 D( ]6 {& o6 H2 ]的。但是,通常来讲,在我们的Release文件当中,并不需要如此小的执行文件。
' S4 v h" G+ n( n G; P如果想达到瘦身的目的,修改为library:MutiThreaded Dll和添加/opt:nowin98已
$ `2 i; r+ E N* p. G9 y经是很好的选择了。其他别的选项在编译的时候或多或少的有警告出现,而且,带/ Y- C) U% S4 B; x0 ]* R
有那些编译选项编出来的执行文件也不一定在各个平台上能够适用。
V: m& S5 W$ ]* V& g* E; G% W: n9 E w1 M9 Q0 L9 P
另外:如果你的执行文件即使通过了这些设定还是比较大的话,也可以通过一些& |! t, u/ |+ k( A: F
EXE文件压缩工具来进行压缩。比如UPX等等。在此不再细说了。# }$ _ {- ~. X& c) i& V* W
: c+ m* A: E1 v: {$ v9 L$ F' t+ f
以上部分的不足之处,还请多多指正。 |
|