找回密码
 加入华同
搜索
黄金广告位联系EMAIL:[email protected] 黄金广告[email protected]
查看: 968|回复: 2

瘦身你的执行文件

[复制链接]
发表于 2006-9-28 21:36:19 | 显示全部楼层 |阅读模式
在网上,有好多绿色软件,不仅功能强大,而且软件本身的体积非常小。有的通常
+ @. ~* K5 l; y只在几十K左右。那他们是怎么做到把软件做的怎么小的呢?现在我手把手的告诉4 D" Y0 y; e: M% f0 L- G( H% {4 g
你如何通过修改程序的编译选项来瘦身你的执行文件& ^, {. Q- X8 v- e
先看一个最典型的程序:
* K' k( ~8 A3 Z! @8 H3 q#include<stdio.h>
* N) l( J# o5 |+ B% p) l5 P# zint main()+ n* d; z, C& u2 _0 l
{
  o2 X! `3 c( V1 V2 t( Y printf("Hello,World");
2 ]5 O* d5 u' i! R$ M5 f return 0;
. N/ I  O1 M" k/ d6 c# ~- t}: \6 M9 ^- U7 s& K
- B0 [' c& G+ T& I* m
上面的程序之所以被称之为典型,是因为他有如下的内容:: Y0 i) h- H3 p( [9 U- {" @
1、系统函数调用:printf
$ |% ]: _* \8 v' r9 J2、有静态数据段+ u- A1 U2 k( b* n+ l" a& ~( W

: f3 q$ l! p8 {# k: y好,现在把此文件放到VisualStudio6.0中进行编译,看看文件有多大。7 |; N' }% N: F
1、用VisualStudio6.0打开HelloWorld.cpp文件,直接按F7。然后点击OK,生成
3 i5 ?1 Q, t+ B4 tProject文件,然后进行编译。编译完成了以后,看看Debug目录下的执行文件的大8 Z) [' L' x+ q' p  V* h
小,为172,096Bytes。' V2 ?( k9 }, q0 o' s( U
1 {4 h- n5 v- \3 I2 N7 M( Q
2、刚才编译的Debug文件,现在修改成Release文件看看。选择Win32 Release,再. T1 @+ U3 D5 H! {, A
编译。察看执行文件大小,现在成了40,960Bytes。看来Debug版本的要比Release) k: L3 g6 E+ |, b% Z- K7 N
的小。/ L) p+ \: S* m3 k3 B! i! `
& G* J+ r" @- `% s; d1 d9 D
3、检查代码优化:发现执行文件的优化是Maximize Speed。那么修改成Minimize
" b5 l& t4 }. o1 R, mSize看看。重新编译,得到执行文件的大小为:40,960Bytes。看来大小没什么变
, q7 y* X. i$ u) _1 g化。其实这是由于我们的代码本身太小的缘故,导致即使变化了也看不出来。
  r0 G( B) b0 N% v% s" u# d! N4 M
4、想想我们程序的main函数是由CRT类库进行引导的。在我们现在的设定当中,由
& Y# S# c7 c) e! R0 J- J于采取的是系统缺省的编译连接方式(缺省为编译为Single Thread,Static" t6 [8 h1 J3 @0 F' Z" w
Library),所以,在我们的执行文件当中,包含了CRT的二进制代码。好,修改编
& B; _" x" ]/ o6 l5 ?7 O1 R/ ~  A: Z6 K/ e译选项:C/C++ => Category:Code Generation => Use run-time
; t! f! {1 H9 v+ klibrary:MutiThreaded Dll。编译看看:执行文件大小变成了16,384Bytes。
* L1 |1 M6 f8 C/ _9 P
( n) W" [" {1 f6 \- e0 d5、刚才的设定确实不错,一下子把执行文件大小减小到了16K。现在用UltraEdit$ r& q% r' `: t1 T% [3 X" o) n
看看执行文件都是些什么内容。结果大吃一惊:基本上都是0。看来这个有减小的
& W! j, v9 w# |( ~! I" U4 t必要了。都知道,执行文件都有自己的代码段,数据段等等,每个段的大小也是采, M6 n( P- U* k3 N0 Q# ]& p" A" s
用编译器缺省设定的。好,我们来修改一下段的大小看看:
4 w+ c1 N# w3 i5 Z6 u& a5.1 连接选项中有一个是/opt:nowin98,意思是将段的大小设定成为Win2000适应; G+ d6 H; X) Z; {6 G9 W
的。编译看看:哇塞,变成了2,560byte。看来这个选项确实把文件变小了N多。1 n) d( Q" R$ ]0 |$ y# g
5.2 在查察连接选项中还有没有什么特别的。发现/align:xx还可以将段大小缩
. |. T7 x0 D3 X" [9 k- R. o! A小。通过UltraEdit察看刚才/opt:nowin98编译出来的文件,发现每个段的大小都8 U: ?. ~! }/ c: ]
是4K的整数倍。看来/align:xx还有减小的趋势。试一把再说:添加连接选项:
( k9 \# u/ F) Q! z5 v* T/align:16(这个大小已经是能够设定的最小的了)。看看结果:1,408Bytes。厉( I5 Q! Z, c5 y4 ?) `2 m) t, V
害,现在代码更小了。
  h2 ^; j8 Y5 ~2 y! B% ~1 W1 I5 R5.3 现在回想起来,执行文件大小有数据段,执行代码段等等,如果把这些段都合
" v0 u5 v  W$ c4 W0 x并起来,是不是就会把段之间的冗余有减小了呢?再试试看:添加选项:
; c8 ?9 Q- ]( f/ z3 y/merge:.data=.text /merge:.rdata=.text。再看看文件大小:1,328bytes。真的
* g' A  K5 @8 f很不错了。
- G' f( C1 s- {8 L; j+ k- e) s% H0 r3 D8 _/ g5 q0 ~0 S
6、刚才的设定确实不错,似乎达到了我们想要的极限了。但是回头想一下,如果0 ]7 z" ~+ K7 P- u, m
没有CRT库的话,会不会更小了?实际上确实这样。添加连接选项: /entry:
( g6 u: L" h+ E- n& @9 ymain,把入口地址直接指向我们的main函数看看。得到592Bytes。
6 t  P5 [+ t: U+ X* F, r2 d6 e8 {! b0 k  j
最终我们得到我们最后的大小592Bytes了。我想这也许是我们通过编译器能够编译7 ?7 {  W+ ~$ u$ p( Z4 Y5 R
出来的最小的代码了。
, D4 t" V+ b5 Z; Z. r5 w2 B' O) C! r  Q$ Z: B
结论:# {# B" _# s9 z) u
通过上述的步骤,我们了解了如何修改那些编译连接选项来达到执行文件瘦身的目1 I& K( a% O/ D, Y$ D
的。但是,通常来讲,在我们的Release文件当中,并不需要如此小的执行文件。! _0 F1 k: T+ X* B6 _& N
如果想达到瘦身的目的,修改为library:MutiThreaded Dll和添加/opt:nowin98已
' g. Q6 `7 n5 Q- w; z# X经是很好的选择了。其他别的选项在编译的时候或多或少的有警告出现,而且,带$ J8 b4 Y* c' q# l
有那些编译选项编出来的执行文件也不一定在各个平台上能够适用。. x% h8 [3 g& s( O

9 u: {  m6 Y/ Q" e) K另外:如果你的执行文件即使通过了这些设定还是比较大的话,也可以通过一些* v1 h$ h8 t. V0 J0 h; r
EXE文件压缩工具来进行压缩。比如UPX等等。在此不再细说了。) y: w! h! Z" c* w

/ r  A/ Y9 j- r& E% r; d1 i以上部分的不足之处,还请多多指正。
发表于 2006-10-3 13:00:07 | 显示全部楼层
谢谢楼主
回复

使用道具 举报

发表于 2006-10-7 16:25:19 | 显示全部楼层
这个如果是楼主的原创,希望能够在细致的解释一下,代码优化部分,可以遵循ood中的reuse一些原则,如抽象工厂,开闭原则等会是更好的解决软件优化的方法。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 加入华同

本版积分规则

Archiver|手机版|小黑屋|华人同志

GMT+8, 2025-4-19 11:04 , Processed in 0.067803 second(s), 5 queries , Redis On.

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表