|
|
|
在网上,有好多绿色软件,不仅功能强大,而且软件本身的体积非常小。有的通常
' j, H4 j) ^4 _% Y+ N只在几十K左右。那他们是怎么做到把软件做的怎么小的呢?现在我手把手的告诉* m! ]. N1 h) Z7 t- B# [" e
你如何通过修改程序的编译选项来瘦身你的执行文件9 q" T& s4 e$ d1 ^8 P
先看一个最典型的程序: , j, U: V2 w# E8 x5 N& i5 R
#include<stdio.h>" S3 f; E+ j/ Z; q" c$ P4 R
int main()
9 M3 f9 d7 T8 F) l{
2 U2 v' I) V! {/ [ N4 q# n# N3 U printf("Hello,World");9 K6 @. {! Z. f8 l5 v0 ]
return 0;
, q* G# M8 w* {6 |' ~6 K* n}! x! [8 p2 s E" }" m* C
7 O' E. a: \9 |
上面的程序之所以被称之为典型,是因为他有如下的内容:' p) q, z- n# y% z* G
1、系统函数调用:printf
! y( d) \ e- g J) W2、有静态数据段2 [# q$ T* H9 @! C6 U
8 x6 u/ Z: b# R8 k: T& w3 e- k
好,现在把此文件放到VisualStudio6.0中进行编译,看看文件有多大。
5 ?$ Q9 t$ q3 S* }. Q) H6 J& r1、用VisualStudio6.0打开HelloWorld.cpp文件,直接按F7。然后点击OK,生成, S& n9 A7 ~2 z6 j; J% k9 {
Project文件,然后进行编译。编译完成了以后,看看Debug目录下的执行文件的大. n- L4 t7 J+ e' M
小,为172,096Bytes。* y& H2 N/ |$ b% q( B0 |
) u" l1 J t5 t* T0 r
2、刚才编译的Debug文件,现在修改成Release文件看看。选择Win32 Release,再3 K( l+ v. F+ T" M
编译。察看执行文件大小,现在成了40,960Bytes。看来Debug版本的要比Release
1 z2 r i9 W: C2 j的小。( y# \+ Y9 p9 M; d( f
8 R. ]! }( R; m. n, ]! B( s3、检查代码优化:发现执行文件的优化是Maximize Speed。那么修改成Minimize
+ a Y( T; W% J6 B% r5 sSize看看。重新编译,得到执行文件的大小为:40,960Bytes。看来大小没什么变
& J6 |: l! v0 w; O4 w7 L0 O化。其实这是由于我们的代码本身太小的缘故,导致即使变化了也看不出来。8 A. q/ R# H5 D" ^4 t9 r6 \/ w
; W# A- P8 M( ~) j4 H4、想想我们程序的main函数是由CRT类库进行引导的。在我们现在的设定当中,由
6 w; t8 L5 O& H* U! P于采取的是系统缺省的编译连接方式(缺省为编译为Single Thread,Static
9 A/ R/ w4 c/ ^" L/ U5 ?) BLibrary),所以,在我们的执行文件当中,包含了CRT的二进制代码。好,修改编
/ C7 X& r- A$ @3 u译选项:C/C++ => Category:Code Generation => Use run-time+ S G3 Y+ Q1 Z" h' B
library:MutiThreaded Dll。编译看看:执行文件大小变成了16,384Bytes。
- N0 F$ Y8 M8 P2 {, j' M. A$ I/ X3 }
R+ C2 v1 g2 u5、刚才的设定确实不错,一下子把执行文件大小减小到了16K。现在用UltraEdit
3 V, i" m" ~: S. J( X; P看看执行文件都是些什么内容。结果大吃一惊:基本上都是0。看来这个有减小的+ t' k* e3 {. U( [5 G4 u! B! l
必要了。都知道,执行文件都有自己的代码段,数据段等等,每个段的大小也是采6 t$ C* ^/ T- f; a! o; C9 I: Q
用编译器缺省设定的。好,我们来修改一下段的大小看看:8 C) \5 H% A- O# ~- w- G
5.1 连接选项中有一个是/opt:nowin98,意思是将段的大小设定成为Win2000适应
, i, D- q* U( B* h* U8 O4 F的。编译看看:哇塞,变成了2,560byte。看来这个选项确实把文件变小了N多。
7 O5 R$ x3 R$ d, L4 X5.2 在查察连接选项中还有没有什么特别的。发现/align:xx还可以将段大小缩
* [# A) s+ A; R8 @5 i1 X0 E; ]$ g小。通过UltraEdit察看刚才/opt:nowin98编译出来的文件,发现每个段的大小都0 P+ u8 ~# g: C. L0 \5 \( k
是4K的整数倍。看来/align:xx还有减小的趋势。试一把再说:添加连接选项:
, [. Z7 G! T' A/align:16(这个大小已经是能够设定的最小的了)。看看结果:1,408Bytes。厉
% w9 e0 T# O% p8 D害,现在代码更小了。; T7 _4 P, ]1 X0 v6 a4 X3 H
5.3 现在回想起来,执行文件大小有数据段,执行代码段等等,如果把这些段都合' J( O7 p# x5 z9 [( r( P
并起来,是不是就会把段之间的冗余有减小了呢?再试试看:添加选项:
, q3 T$ o! g0 Y# U1 x# ^/merge:.data=.text /merge:.rdata=.text。再看看文件大小:1,328bytes。真的
3 U$ y8 G: p! F0 g很不错了。
0 m2 S7 c9 H1 @2 }( i$ g4 _
" o; V, D* b+ R( x* s% x3 g6、刚才的设定确实不错,似乎达到了我们想要的极限了。但是回头想一下,如果 G2 {0 k* e# q- ]4 o% m2 |7 j; F
没有CRT库的话,会不会更小了?实际上确实这样。添加连接选项: /entry:
8 y' g A! F* W* q: v1 ? Dmain,把入口地址直接指向我们的main函数看看。得到592Bytes。7 ?; g" Y2 k) T6 W
6 E1 W1 o0 I C
最终我们得到我们最后的大小592Bytes了。我想这也许是我们通过编译器能够编译$ X, K, U i: t' n3 K
出来的最小的代码了。4 U( L' G5 C5 d
9 q# H# `; C2 H/ ?7 y8 q3 p; ~% R
结论:" O, w7 a7 f3 a8 g# I
通过上述的步骤,我们了解了如何修改那些编译连接选项来达到执行文件瘦身的目
( s' z. [; l4 q. L3 g9 T的。但是,通常来讲,在我们的Release文件当中,并不需要如此小的执行文件。# L: Z4 @# h3 ]! |' Y3 @% T Q
如果想达到瘦身的目的,修改为library:MutiThreaded Dll和添加/opt:nowin98已3 k( p& T& e0 @1 j' _: k
经是很好的选择了。其他别的选项在编译的时候或多或少的有警告出现,而且,带
: h9 R. z$ E8 t- n6 A6 l# |* s有那些编译选项编出来的执行文件也不一定在各个平台上能够适用。0 r3 L- g+ m. A% m, w8 P/ ?
) u: S# A( U1 V* P$ F- T4 ]8 A另外:如果你的执行文件即使通过了这些设定还是比较大的话,也可以通过一些
7 P: R Q2 ~6 vEXE文件压缩工具来进行压缩。比如UPX等等。在此不再细说了。% L. Y! S5 M5 s3 v; e: ?' p3 Q% E
$ q5 S+ z7 Q- A8 C
以上部分的不足之处,还请多多指正。 |
|