|
|
|
在网上,有好多绿色软件,不仅功能强大,而且软件本身的体积非常小。有的通常' {8 s# M5 Q, E1 }( T0 k
只在几十K左右。那他们是怎么做到把软件做的怎么小的呢?现在我手把手的告诉. W! W! _: h# P$ v
你如何通过修改程序的编译选项来瘦身你的执行文件
7 R S) L& A0 j; V2 \ P7 A1 I先看一个最典型的程序:
' _8 J4 X4 I( a& I5 ~#include<stdio.h>( Y1 k8 i/ B7 b" I
int main(): X4 ~7 y9 r" k4 v
{
& P) I- e, J7 P" K, Z printf("Hello,World");$ H/ y V" X. c+ i, z; a( q. ]
return 0;9 t' g+ G0 W4 _. x" P! ^
}1 K" ]: ~# `- A: H4 P+ G4 k
1 `1 e# G+ P& u$ \/ `+ G上面的程序之所以被称之为典型,是因为他有如下的内容:
/ [+ w( c. _; B: g( M1、系统函数调用:printf; m" V# Y: D3 T+ N
2、有静态数据段
" S b* ^" r# M
* ?% D. k' P3 i8 y6 J好,现在把此文件放到VisualStudio6.0中进行编译,看看文件有多大。, G; R5 e* X. R* i! z2 W3 ?/ @
1、用VisualStudio6.0打开HelloWorld.cpp文件,直接按F7。然后点击OK,生成
6 L4 b% {1 Q' F. b/ n+ rProject文件,然后进行编译。编译完成了以后,看看Debug目录下的执行文件的大
2 J( x6 h! @, y6 K# K: h- _) l4 M小,为172,096Bytes。( u- |7 j7 u% ]5 r# B" t
' Y4 d3 n5 v8 Z; v, Y
2、刚才编译的Debug文件,现在修改成Release文件看看。选择Win32 Release,再$ T9 A7 K4 g9 q7 ^
编译。察看执行文件大小,现在成了40,960Bytes。看来Debug版本的要比Release
# e2 X" h& ]5 J* s0 ~5 w& r的小。
* h+ @1 Y) o" ~% p2 T
$ o& |: a0 I' z3 @! ~; b& Z3、检查代码优化:发现执行文件的优化是Maximize Speed。那么修改成Minimize
4 n/ q4 {0 ^) xSize看看。重新编译,得到执行文件的大小为:40,960Bytes。看来大小没什么变- _' q: d, [ n8 G$ @
化。其实这是由于我们的代码本身太小的缘故,导致即使变化了也看不出来。! [9 r& ~; K- Q3 M2 p& u |
+ w% a# c* E* ~) @# a4 U h9 N! e! ]
4、想想我们程序的main函数是由CRT类库进行引导的。在我们现在的设定当中,由1 r) {# [8 M. E( m W) J. x
于采取的是系统缺省的编译连接方式(缺省为编译为Single Thread,Static
! _- ?, L, T" J# SLibrary),所以,在我们的执行文件当中,包含了CRT的二进制代码。好,修改编
0 [( ^3 C4 A# z$ @8 }9 j3 f) a: s( m译选项:C/C++ => Category:Code Generation => Use run-time
" U7 I8 V0 x9 ilibrary:MutiThreaded Dll。编译看看:执行文件大小变成了16,384Bytes。) j2 y* P1 L Y: a
2 \, Z! D. r! n- [5、刚才的设定确实不错,一下子把执行文件大小减小到了16K。现在用UltraEdit
1 Z! v! s" Y, E6 {9 f看看执行文件都是些什么内容。结果大吃一惊:基本上都是0。看来这个有减小的
M/ p1 }/ b/ _8 L/ H: ~$ p" q必要了。都知道,执行文件都有自己的代码段,数据段等等,每个段的大小也是采
! ~* e$ Q# c# ]" U* D0 j- S) A( [ M用编译器缺省设定的。好,我们来修改一下段的大小看看:" d! W5 J* u4 O+ o7 M* ^5 J2 X
5.1 连接选项中有一个是/opt:nowin98,意思是将段的大小设定成为Win2000适应! F9 a* C9 G) ~. f& z4 P4 ?3 C' X o
的。编译看看:哇塞,变成了2,560byte。看来这个选项确实把文件变小了N多。' ` D0 ]. z% H
5.2 在查察连接选项中还有没有什么特别的。发现/align:xx还可以将段大小缩
$ {9 _6 R6 t+ ^+ `小。通过UltraEdit察看刚才/opt:nowin98编译出来的文件,发现每个段的大小都
: c9 S7 e$ i0 p是4K的整数倍。看来/align:xx还有减小的趋势。试一把再说:添加连接选项:, @& v+ w# j9 E9 y( ?' }- j
/align:16(这个大小已经是能够设定的最小的了)。看看结果:1,408Bytes。厉
9 `% \% \2 i3 j" a" k5 {8 A- R害,现在代码更小了。
! k0 x8 w8 I$ o; _5.3 现在回想起来,执行文件大小有数据段,执行代码段等等,如果把这些段都合$ I0 v: T& l" K/ F( I! u
并起来,是不是就会把段之间的冗余有减小了呢?再试试看:添加选项:8 z8 h& K9 \( M# U8 g
/merge:.data=.text /merge:.rdata=.text。再看看文件大小:1,328bytes。真的
" A4 L5 d# z! X# x8 _# L很不错了。2 A! k) S3 b0 e0 o+ L p ^
' i$ G& O8 d% K7 K* i6 Q! @6、刚才的设定确实不错,似乎达到了我们想要的极限了。但是回头想一下,如果. J( |' F& d+ |% _
没有CRT库的话,会不会更小了?实际上确实这样。添加连接选项: /entry:; r4 H# `9 ~* m
main,把入口地址直接指向我们的main函数看看。得到592Bytes。1 e. M; w5 w" i/ Y& t
5 F/ u' h) Z8 I6 P; e最终我们得到我们最后的大小592Bytes了。我想这也许是我们通过编译器能够编译
4 D V7 b& z1 s0 y8 p- Y7 J出来的最小的代码了。
" k3 ~5 p. i% O0 q
$ u1 d0 d7 L" F) W% L结论:' R. E; r, K7 C
通过上述的步骤,我们了解了如何修改那些编译连接选项来达到执行文件瘦身的目$ g% D8 a# E# e+ V) u' Q
的。但是,通常来讲,在我们的Release文件当中,并不需要如此小的执行文件。
+ B& t1 Y4 u! k# I/ e& ^如果想达到瘦身的目的,修改为library:MutiThreaded Dll和添加/opt:nowin98已4 i) K, w4 d5 D' b4 f4 m/ R. T0 O0 \3 t
经是很好的选择了。其他别的选项在编译的时候或多或少的有警告出现,而且,带
# D8 z) l' h! i* z% _$ c3 j2 s有那些编译选项编出来的执行文件也不一定在各个平台上能够适用。
# b/ h" s6 i+ }6 c$ F( ~: G. {- p: q$ E W0 Y6 \
另外:如果你的执行文件即使通过了这些设定还是比较大的话,也可以通过一些
: x T/ P+ l9 h! UEXE文件压缩工具来进行压缩。比如UPX等等。在此不再细说了。6 K. Z/ D; N# }9 t# T, V
- O; ^3 x( A' k" [: \' t% h
以上部分的不足之处,还请多多指正。 |
|