|
|
|
在网上,有好多绿色软件,不仅功能强大,而且软件本身的体积非常小。有的通常3 b g! Z9 i* i, c9 w: u! n' ]
只在几十K左右。那他们是怎么做到把软件做的怎么小的呢?现在我手把手的告诉+ J3 i( {( g( W
你如何通过修改程序的编译选项来瘦身你的执行文件
/ E9 g& F, K' Y/ r2 F( @先看一个最典型的程序:
/ k) K: O, U% R( ]/ |! t#include<stdio.h>" f* u$ U+ _# B% l* y
int main()+ Q8 \* d4 y, m$ T% i1 d1 u
{
2 b0 ^# t. ]7 Y& }2 j" S printf("Hello,World");. k/ Y" D$ W2 T7 r4 V
return 0;
. u( v3 c& b0 p9 N}, t* K1 D. C; D, \( e) _! R
* H7 n' `# N! L. G$ B6 i. K9 a上面的程序之所以被称之为典型,是因为他有如下的内容:
- ^1 w* q* e0 Q* ?) n1、系统函数调用:printf0 [2 Y; Q U8 x/ p! ?
2、有静态数据段
& h$ h1 ?+ ?5 ]9 D. @( K. F% z1 a# D5 z
好,现在把此文件放到VisualStudio6.0中进行编译,看看文件有多大。
" R) S7 v, d7 I, H2 Z4 o0 g1、用VisualStudio6.0打开HelloWorld.cpp文件,直接按F7。然后点击OK,生成
* q4 P6 f7 X( v6 ?1 H" TProject文件,然后进行编译。编译完成了以后,看看Debug目录下的执行文件的大
1 D' o4 j' W& S2 r小,为172,096Bytes。3 A. o- r4 E7 a! v- M4 h
+ ^4 E0 K: }9 H, Z$ U
2、刚才编译的Debug文件,现在修改成Release文件看看。选择Win32 Release,再! a! B0 v+ J8 X3 m8 n2 n+ B. e
编译。察看执行文件大小,现在成了40,960Bytes。看来Debug版本的要比Release
$ h: i$ [2 D) C8 t! k的小。: T) Q' {/ o* F& J" S, }* L
: f% ^' G7 Q' m1 {% L0 R& s3、检查代码优化:发现执行文件的优化是Maximize Speed。那么修改成Minimize- Z, V" ]& {, O3 Z: k3 R
Size看看。重新编译,得到执行文件的大小为:40,960Bytes。看来大小没什么变9 p- O4 {& `& q/ a+ e5 o
化。其实这是由于我们的代码本身太小的缘故,导致即使变化了也看不出来。. F, V2 o) \8 S, R# l
' N: k- v" u+ R$ B
4、想想我们程序的main函数是由CRT类库进行引导的。在我们现在的设定当中,由
) u5 X* `( S; V# A p% H于采取的是系统缺省的编译连接方式(缺省为编译为Single Thread,Static
# t& B) @4 I# BLibrary),所以,在我们的执行文件当中,包含了CRT的二进制代码。好,修改编
5 l5 H1 b7 n$ u# M$ ?, M译选项:C/C++ => Category:Code Generation => Use run-time: Q6 X& J# t0 c0 \* _) R
library:MutiThreaded Dll。编译看看:执行文件大小变成了16,384Bytes。9 i2 c% _2 R0 A0 y- k p) q1 a9 s
! w- X4 a7 v* e' l9 t; X1 A! U% _0 o/ `5、刚才的设定确实不错,一下子把执行文件大小减小到了16K。现在用UltraEdit
+ x H9 @. V1 u% s3 J看看执行文件都是些什么内容。结果大吃一惊:基本上都是0。看来这个有减小的( g4 L2 O3 j% l3 d
必要了。都知道,执行文件都有自己的代码段,数据段等等,每个段的大小也是采
$ n% u' N1 m' S$ }用编译器缺省设定的。好,我们来修改一下段的大小看看:- a1 Y5 ]1 [& L2 V" @. O
5.1 连接选项中有一个是/opt:nowin98,意思是将段的大小设定成为Win2000适应
% H$ }* ^8 E( e$ t! ]$ m的。编译看看:哇塞,变成了2,560byte。看来这个选项确实把文件变小了N多。! h- ~5 |+ ~0 O( K' B6 e
5.2 在查察连接选项中还有没有什么特别的。发现/align:xx还可以将段大小缩
, [/ J" Y- |4 p, N$ s2 S小。通过UltraEdit察看刚才/opt:nowin98编译出来的文件,发现每个段的大小都# `% l5 N7 r% M! S/ G
是4K的整数倍。看来/align:xx还有减小的趋势。试一把再说:添加连接选项:4 J" g, H& x" i' x X
/align:16(这个大小已经是能够设定的最小的了)。看看结果:1,408Bytes。厉' a9 _. L; @$ B" |5 g
害,现在代码更小了。
5 V: k p) {- Z6 K8 @5.3 现在回想起来,执行文件大小有数据段,执行代码段等等,如果把这些段都合2 y! F+ F; u6 o3 @0 p1 u. G) |( A6 t
并起来,是不是就会把段之间的冗余有减小了呢?再试试看:添加选项:) X2 _4 U; m# l% ^& Z/ j
/merge:.data=.text /merge:.rdata=.text。再看看文件大小:1,328bytes。真的! x$ h6 c9 ]* t* H& X) t+ N
很不错了。
0 d, c" d5 y$ v5 F. y/ H! ~+ V
" `# b! q+ C @' l" K. i" ?/ l& I' L6、刚才的设定确实不错,似乎达到了我们想要的极限了。但是回头想一下,如果
/ ?2 ^: g* K% T L! e0 @没有CRT库的话,会不会更小了?实际上确实这样。添加连接选项: /entry:
_9 p, V& ?( K( X- C d9 Smain,把入口地址直接指向我们的main函数看看。得到592Bytes。
( h6 W$ n9 y2 {* M5 G. o% x
; t2 M$ a p. v& m" i/ f1 ~- m! `; A最终我们得到我们最后的大小592Bytes了。我想这也许是我们通过编译器能够编译0 [! d8 d% ?4 ^$ r: |3 H
出来的最小的代码了。
4 K+ V4 H% o! a$ w* c, l7 |7 H" R- U, m& r1 V+ g
结论:, E5 o0 `& Z F6 l0 w
通过上述的步骤,我们了解了如何修改那些编译连接选项来达到执行文件瘦身的目' e3 G2 B2 X$ j+ l6 R
的。但是,通常来讲,在我们的Release文件当中,并不需要如此小的执行文件。
+ q1 @/ U( t7 e如果想达到瘦身的目的,修改为library:MutiThreaded Dll和添加/opt:nowin98已
0 E/ I, [9 @; y/ F2 D! m经是很好的选择了。其他别的选项在编译的时候或多或少的有警告出现,而且,带
9 w' D# M" s% X( z' ?有那些编译选项编出来的执行文件也不一定在各个平台上能够适用。! z0 e( s9 o3 U" I' ^9 s
* ?3 E! \0 p7 { ~; f* a另外:如果你的执行文件即使通过了这些设定还是比较大的话,也可以通过一些5 _; o# b5 |; H0 |9 q' Y$ R
EXE文件压缩工具来进行压缩。比如UPX等等。在此不再细说了。
% a; b& `2 w: s) W7 w. E! [2 I0 c0 P1 H) K
以上部分的不足之处,还请多多指正。 |
|