|
|
|
在网上,有好多绿色软件,不仅功能强大,而且软件本身的体积非常小。有的通常$ v0 ^0 J2 F! l
只在几十K左右。那他们是怎么做到把软件做的怎么小的呢?现在我手把手的告诉
: k! s3 {5 f1 t1 i+ U3 ~9 l你如何通过修改程序的编译选项来瘦身你的执行文件
6 W7 Q6 f6 H5 h先看一个最典型的程序: ' e9 B9 |# z* d# [8 N: y
#include<stdio.h>+ L, e, h- O) k) m- J5 R
int main()
9 S4 ^3 w9 X8 @{
$ [( G) j1 _+ U# b' y printf("Hello,World");4 M" w2 o" n( {! J( t2 G/ t# s3 p4 R- x
return 0;
. r( o- @7 |- J3 J}- Q2 z A2 Z1 _1 x; m
1 z7 \! m2 z; g9 ?: T7 B8 x! K上面的程序之所以被称之为典型,是因为他有如下的内容:+ V" ^ J+ k& s$ e" N2 W
1、系统函数调用:printf' G( f6 p! J0 o! |
2、有静态数据段: N. ]) j; @: o7 z5 I6 Q- T# r9 j) r
/ Z4 J: |& a$ `; v) Z9 z; d好,现在把此文件放到VisualStudio6.0中进行编译,看看文件有多大。
% j$ h T8 c" M0 ]1、用VisualStudio6.0打开HelloWorld.cpp文件,直接按F7。然后点击OK,生成
" d$ r* k8 `9 D4 ?. S( M" wProject文件,然后进行编译。编译完成了以后,看看Debug目录下的执行文件的大
) {" f! V8 S1 {& `1 `# R3 ?! ^小,为172,096Bytes。
6 B& C8 w h/ `4 Z
& o: ^) u2 u3 w2、刚才编译的Debug文件,现在修改成Release文件看看。选择Win32 Release,再1 E/ [: }0 R/ D8 u9 E# D7 P: O
编译。察看执行文件大小,现在成了40,960Bytes。看来Debug版本的要比Release
' A, K, i0 d! K0 T/ N/ [3 C; U的小。* }& k8 C# q2 B3 Z6 ^: p( x
" C: q% m7 d# b6 I' y" M3、检查代码优化:发现执行文件的优化是Maximize Speed。那么修改成Minimize2 W* g7 Z1 b! |. s
Size看看。重新编译,得到执行文件的大小为:40,960Bytes。看来大小没什么变* h5 u$ J# k s0 H
化。其实这是由于我们的代码本身太小的缘故,导致即使变化了也看不出来。
# B6 y( h2 R4 M' u& n; E+ R. A$ B2 A- O5 d0 A& j
4、想想我们程序的main函数是由CRT类库进行引导的。在我们现在的设定当中,由
7 @: I: ]* Y4 T2 b于采取的是系统缺省的编译连接方式(缺省为编译为Single Thread,Static
# ]' P- X ]1 x( `3 f- xLibrary),所以,在我们的执行文件当中,包含了CRT的二进制代码。好,修改编
0 u. {' U( B+ v8 w6 ^( U& w' r译选项:C/C++ => Category:Code Generation => Use run-time5 S4 \7 b% O2 H
library:MutiThreaded Dll。编译看看:执行文件大小变成了16,384Bytes。
8 K( g& ?% }# l4 D9 z6 |# b9 t9 B+ M
5、刚才的设定确实不错,一下子把执行文件大小减小到了16K。现在用UltraEdit
1 ^; C7 n q7 E看看执行文件都是些什么内容。结果大吃一惊:基本上都是0。看来这个有减小的* Q2 \) m( q( @. \/ u& j
必要了。都知道,执行文件都有自己的代码段,数据段等等,每个段的大小也是采
! T, y, z0 v8 N! b% f0 i' f用编译器缺省设定的。好,我们来修改一下段的大小看看:
* P! n$ H' @& C$ G& F6 Q& K8 d5.1 连接选项中有一个是/opt:nowin98,意思是将段的大小设定成为Win2000适应
/ b: l1 o$ Q% |( k9 b* c. h/ Z的。编译看看:哇塞,变成了2,560byte。看来这个选项确实把文件变小了N多。
9 k, T" I8 r8 W- ?5.2 在查察连接选项中还有没有什么特别的。发现/align:xx还可以将段大小缩
/ Z6 `; t; b$ [! Z9 U小。通过UltraEdit察看刚才/opt:nowin98编译出来的文件,发现每个段的大小都 w0 E6 K8 c. E2 G* k' u
是4K的整数倍。看来/align:xx还有减小的趋势。试一把再说:添加连接选项:. i, r7 ^' B$ \9 n: G$ z/ e
/align:16(这个大小已经是能够设定的最小的了)。看看结果:1,408Bytes。厉
+ C; L$ c& V/ }# m- W: i害,现在代码更小了。
2 R! J# M/ H2 t6 i5.3 现在回想起来,执行文件大小有数据段,执行代码段等等,如果把这些段都合
, r J' F7 q; D3 o1 B$ x并起来,是不是就会把段之间的冗余有减小了呢?再试试看:添加选项:: J o: a3 v) G2 \4 v' ]
/merge:.data=.text /merge:.rdata=.text。再看看文件大小:1,328bytes。真的
' w8 V3 v; ^: `; A) j" p9 K很不错了。9 ] N& B$ M* \" h& O
! G8 q) h6 K; j6 T4 t
6、刚才的设定确实不错,似乎达到了我们想要的极限了。但是回头想一下,如果) g1 z$ g" m2 F
没有CRT库的话,会不会更小了?实际上确实这样。添加连接选项: /entry:
! ]9 B0 D4 y# _1 h: Lmain,把入口地址直接指向我们的main函数看看。得到592Bytes。
: \0 G4 u, p; @% s$ o- a& ], D9 n: m* C" ?) u! V9 P9 P
最终我们得到我们最后的大小592Bytes了。我想这也许是我们通过编译器能够编译4 R: `& K! L# J+ k# P3 `. [
出来的最小的代码了。
0 U: B% A" t" a% Z& G+ D" s; t8 n1 O9 i- X
结论:
7 R; B, o+ I% i5 N+ o! w4 |通过上述的步骤,我们了解了如何修改那些编译连接选项来达到执行文件瘦身的目
8 p' h* V2 L) u& F! |, v的。但是,通常来讲,在我们的Release文件当中,并不需要如此小的执行文件。; q6 x( f- a9 g" Z8 b3 d) r8 B
如果想达到瘦身的目的,修改为library:MutiThreaded Dll和添加/opt:nowin98已/ M6 x0 U: Q( i ~6 P
经是很好的选择了。其他别的选项在编译的时候或多或少的有警告出现,而且,带 e3 Z% n _3 {! Z# o
有那些编译选项编出来的执行文件也不一定在各个平台上能够适用。; O( C- g, f, c/ E- r1 `
$ r; U# ]6 j& i% |4 Q" U& Q' L% Q* z
另外:如果你的执行文件即使通过了这些设定还是比较大的话,也可以通过一些
5 N1 @) Q# W0 C+ q) v9 VEXE文件压缩工具来进行压缩。比如UPX等等。在此不再细说了。! _' R1 I) l# L. ~
8 D. j: D' U$ V8 y+ |" b! `' g以上部分的不足之处,还请多多指正。 |
|