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

瘦身你的执行文件

[复制链接]
发表于 2006-9-28 21:36:19 | 显示全部楼层 |阅读模式
在网上,有好多绿色软件,不仅功能强大,而且软件本身的体积非常小。有的通常
5 C' }# q6 C% A: K; E* f/ p; `# }! E只在几十K左右。那他们是怎么做到把软件做的怎么小的呢?现在我手把手的告诉5 K: u4 ]+ E/ [
你如何通过修改程序的编译选项来瘦身你的执行文件
- ~" f$ I' ^% f7 X2 B) @( o先看一个最典型的程序:
' }- O9 T+ v9 h: N" r#include<stdio.h>
5 P+ Y1 {4 B5 @; R$ F. `, cint main()7 f4 V8 ~$ N; H6 d$ J  d' _
{6 |+ R& t- _) q$ `  j6 v4 b
printf("Hello,World");
/ l4 Y4 T9 ?) b# J  M) r: d return 0;
0 n% \+ g& R' N5 e' g5 U) m$ I}5 T. v% p, D" L0 x# n% A( @' F! @2 Z

- ?/ \9 @5 @! u: I1 _& A' K上面的程序之所以被称之为典型,是因为他有如下的内容:+ U* p$ |0 i7 M7 O# e
1、系统函数调用:printf
6 W+ |+ Q3 x9 o5 o1 ]) e8 h2、有静态数据段
& Z' i2 ^- Q8 h. x& ?6 S5 j3 L$ a- ]5 B
好,现在把此文件放到VisualStudio6.0中进行编译,看看文件有多大。
. W& d5 z1 {2 e9 b) h1、用VisualStudio6.0打开HelloWorld.cpp文件,直接按F7。然后点击OK,生成6 h" ?1 s$ A: |: S: f' a+ X( f$ ]5 @
Project文件,然后进行编译。编译完成了以后,看看Debug目录下的执行文件的大' K) J0 K9 m1 H6 B" v, o8 Z, J+ T
小,为172,096Bytes。+ q+ e2 n% e; Q; a3 @9 a
" }! i3 {( |) d; a8 u
2、刚才编译的Debug文件,现在修改成Release文件看看。选择Win32 Release,再: t" V& a# ?, ?' g* t) n$ j& E
编译。察看执行文件大小,现在成了40,960Bytes。看来Debug版本的要比Release
: u, }7 T& n$ @- i% H' `; u$ K% |! o; X的小。) p3 w( Z0 Z: \5 D! {% E7 Y

% M# r0 S9 P2 }7 d  ?5 Y1 X3、检查代码优化:发现执行文件的优化是Maximize Speed。那么修改成Minimize
& u: G3 ^0 q+ @Size看看。重新编译,得到执行文件的大小为:40,960Bytes。看来大小没什么变
/ D% O; Z/ ~. W( J化。其实这是由于我们的代码本身太小的缘故,导致即使变化了也看不出来。
! O4 L% X5 T5 s2 H! v) ?: l0 \" }; A4 b2 K/ ~9 M, ?0 \
4、想想我们程序的main函数是由CRT类库进行引导的。在我们现在的设定当中,由* H1 h1 \6 W" v$ o+ L1 J* S
于采取的是系统缺省的编译连接方式(缺省为编译为Single Thread,Static' T8 X5 W4 L% @# s8 p/ j: e
Library),所以,在我们的执行文件当中,包含了CRT的二进制代码。好,修改编1 n  T4 w- n1 U. r
译选项:C/C++ => Category:Code Generation => Use run-time
" y8 Q- j  `( \5 o4 Mlibrary:MutiThreaded Dll。编译看看:执行文件大小变成了16,384Bytes。! I- @0 [0 `( c( z* R# X: y" f

8 ~0 k3 Q- E5 Z! J5、刚才的设定确实不错,一下子把执行文件大小减小到了16K。现在用UltraEdit
" I2 O8 z- E4 S- `& [1 R看看执行文件都是些什么内容。结果大吃一惊:基本上都是0。看来这个有减小的
& g( j. H; I0 w6 m/ `& I必要了。都知道,执行文件都有自己的代码段,数据段等等,每个段的大小也是采
- I3 `/ s% _1 I用编译器缺省设定的。好,我们来修改一下段的大小看看:
5 w5 M. \* q0 V5.1 连接选项中有一个是/opt:nowin98,意思是将段的大小设定成为Win2000适应' \% z' \3 c7 y8 I
的。编译看看:哇塞,变成了2,560byte。看来这个选项确实把文件变小了N多。
9 F. L8 z  N. j8 z9 H5.2 在查察连接选项中还有没有什么特别的。发现/align:xx还可以将段大小缩$ d% @) e! r5 X9 H% n8 t
小。通过UltraEdit察看刚才/opt:nowin98编译出来的文件,发现每个段的大小都, r4 M; G$ j* H: q, I, B
是4K的整数倍。看来/align:xx还有减小的趋势。试一把再说:添加连接选项:
# F  r# o+ v7 A: N/align:16(这个大小已经是能够设定的最小的了)。看看结果:1,408Bytes。厉
- c2 t& M5 _- F0 b害,现在代码更小了。, E% Z. O# X) e
5.3 现在回想起来,执行文件大小有数据段,执行代码段等等,如果把这些段都合
$ P, n8 b( y3 V5 @并起来,是不是就会把段之间的冗余有减小了呢?再试试看:添加选项:, P7 w/ y/ O& c& @' q$ V
/merge:.data=.text /merge:.rdata=.text。再看看文件大小:1,328bytes。真的
* l; o2 h/ ?- g* M/ H! r% K9 k0 f很不错了。& B2 e& i; o: T9 I  v; G
8 x( T* S5 ?- n! Q) |2 x+ R% Y
6、刚才的设定确实不错,似乎达到了我们想要的极限了。但是回头想一下,如果1 b% y6 ^. M" y4 w2 }* C
没有CRT库的话,会不会更小了?实际上确实这样。添加连接选项: /entry:5 N$ H( K' B: b! X0 M' t
main,把入口地址直接指向我们的main函数看看。得到592Bytes。+ v" a6 k1 i3 m% ~' M$ I) ?
+ z+ }5 N) p( q: T
最终我们得到我们最后的大小592Bytes了。我想这也许是我们通过编译器能够编译: g' S: }" s# q, l
出来的最小的代码了。
6 j% @: e! a( `$ J2 r8 n
( j5 C" X8 w1 p" \; y& q2 e1 E% s3 m& m结论:* i, j- S8 J# R6 L2 x- z/ S
通过上述的步骤,我们了解了如何修改那些编译连接选项来达到执行文件瘦身的目: A; i6 Y3 ^0 U( P/ w' i* B0 j
的。但是,通常来讲,在我们的Release文件当中,并不需要如此小的执行文件。( U5 M! @1 m) R
如果想达到瘦身的目的,修改为library:MutiThreaded Dll和添加/opt:nowin98已% Z, ~: x& x( m9 r7 [
经是很好的选择了。其他别的选项在编译的时候或多或少的有警告出现,而且,带
9 ?+ H, s* Z. C7 X  K8 ~' Y7 k& h有那些编译选项编出来的执行文件也不一定在各个平台上能够适用。- r7 i/ @3 C) \/ V" \5 @, v
# l+ ?7 D4 C0 T
另外:如果你的执行文件即使通过了这些设定还是比较大的话,也可以通过一些
* B- j9 Y; G- f. w. D( y" N0 SEXE文件压缩工具来进行压缩。比如UPX等等。在此不再细说了。
; k/ }, s+ g1 p; M
  Y; E6 S3 u6 l8 K以上部分的不足之处,还请多多指正。
发表于 2006-10-3 13:00:07 | 显示全部楼层
谢谢楼主
回复

使用道具 举报

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

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-7-25 01:46 , Processed in 0.083130 second(s), 4 queries , Redis On.

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

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