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

瘦身你的执行文件

[复制链接]
发表于 2006-9-28 21:36:19 | 显示全部楼层 |阅读模式
在网上,有好多绿色软件,不仅功能强大,而且软件本身的体积非常小。有的通常
2 E9 R/ A- R+ ~3 E6 t! U* `! v4 O只在几十K左右。那他们是怎么做到把软件做的怎么小的呢?现在我手把手的告诉2 I, e  v- [2 e
你如何通过修改程序的编译选项来瘦身你的执行文件
( F6 L* ~5 a  D" w先看一个最典型的程序:
9 {( O0 ]. Q0 r) T. C+ j- O& t#include<stdio.h>* F5 R, g* T# |8 R. u
int main()
4 o0 a: j. v$ v6 _! ?5 W  |, D7 t{2 }2 B+ [( F" D- y" O* Y
printf("Hello,World");
1 i- D/ b5 }+ o' ?) W, a' u; D return 0;, M; o! {& y- p8 S
}, C5 {6 f3 C+ u) D  ?7 V

: N# q5 _& }* |% I0 O; h' l( e上面的程序之所以被称之为典型,是因为他有如下的内容:6 o' `/ [5 h& }9 s( P
1、系统函数调用:printf
. S9 \4 Q  {1 O0 _2、有静态数据段" x1 B9 ?* t7 C' B7 t) [5 {& \

4 f; z7 ~5 O  N7 W" R% T好,现在把此文件放到VisualStudio6.0中进行编译,看看文件有多大。
# v$ @9 {0 k9 l9 b1 L; t1、用VisualStudio6.0打开HelloWorld.cpp文件,直接按F7。然后点击OK,生成! R  e+ V; C5 b  n) A* v
Project文件,然后进行编译。编译完成了以后,看看Debug目录下的执行文件的大; t4 J4 d$ @) u& C9 e
小,为172,096Bytes。
' `% l0 j8 |$ x7 T6 `+ i) _
2 u5 S- J9 v" H2、刚才编译的Debug文件,现在修改成Release文件看看。选择Win32 Release,再, d, r; ~% e# ~  d9 Z2 ?( C, M$ f9 F
编译。察看执行文件大小,现在成了40,960Bytes。看来Debug版本的要比Release! ?% R8 z9 a1 n3 b8 `- K$ ^0 h- D# R
的小。8 }- w* O# B2 \0 a# t" q
: `" z& w$ g7 {4 u
3、检查代码优化:发现执行文件的优化是Maximize Speed。那么修改成Minimize
4 v; G+ e8 u. c% h$ RSize看看。重新编译,得到执行文件的大小为:40,960Bytes。看来大小没什么变$ p# N) W* `! F  ~( O
化。其实这是由于我们的代码本身太小的缘故,导致即使变化了也看不出来。
! E3 V- r, y- z5 E) W2 V
+ f' [# ?0 e# k+ S) W. d  Z) {% w4、想想我们程序的main函数是由CRT类库进行引导的。在我们现在的设定当中,由
$ o9 Y1 ]+ n2 |3 u于采取的是系统缺省的编译连接方式(缺省为编译为Single Thread,Static0 U7 S* _" C$ S' A+ w( v
Library),所以,在我们的执行文件当中,包含了CRT的二进制代码。好,修改编
# W+ `8 x* J% s" Y# V4 w  T# e) }! S译选项:C/C++ => Category:Code Generation => Use run-time3 e9 I7 n! L4 O! t* j
library:MutiThreaded Dll。编译看看:执行文件大小变成了16,384Bytes。
! t- c% y" F1 |: ^
: z9 K" A( v% c5 V5、刚才的设定确实不错,一下子把执行文件大小减小到了16K。现在用UltraEdit
' a1 k3 {, q5 S0 c6 m* A& E看看执行文件都是些什么内容。结果大吃一惊:基本上都是0。看来这个有减小的' H9 W! k$ y* f# ]0 e7 g& w
必要了。都知道,执行文件都有自己的代码段,数据段等等,每个段的大小也是采
1 a9 B8 E4 y9 L( k7 k) A用编译器缺省设定的。好,我们来修改一下段的大小看看:
: J2 i; P$ e. P0 ^9 J1 t3 u5.1 连接选项中有一个是/opt:nowin98,意思是将段的大小设定成为Win2000适应
; E$ e  ^- N- w5 }' T! T的。编译看看:哇塞,变成了2,560byte。看来这个选项确实把文件变小了N多。& ?9 k8 w) [$ i2 [/ u+ r- C8 H
5.2 在查察连接选项中还有没有什么特别的。发现/align:xx还可以将段大小缩  a* k+ K. E3 \7 X/ z
小。通过UltraEdit察看刚才/opt:nowin98编译出来的文件,发现每个段的大小都6 C/ |/ u. v  Y2 k6 n/ p5 N
是4K的整数倍。看来/align:xx还有减小的趋势。试一把再说:添加连接选项:
" q1 `- i3 W( q9 O# V/align:16(这个大小已经是能够设定的最小的了)。看看结果:1,408Bytes。厉
' w% B) R4 b8 C害,现在代码更小了。* r4 P* M6 ]# b8 s& H
5.3 现在回想起来,执行文件大小有数据段,执行代码段等等,如果把这些段都合, ~) K' g: |$ Z# T- Z$ G( {
并起来,是不是就会把段之间的冗余有减小了呢?再试试看:添加选项:$ x" K% L8 X! ^- v4 z5 W
/merge:.data=.text /merge:.rdata=.text。再看看文件大小:1,328bytes。真的
; G( @: ^6 r. S( V; D# o很不错了。( V2 z& r& J1 d% t" A( R2 [0 o

/ q5 G  U* S9 W# n: z6、刚才的设定确实不错,似乎达到了我们想要的极限了。但是回头想一下,如果
  b/ L2 D% }& {4 o+ L7 L$ \  H8 S' p没有CRT库的话,会不会更小了?实际上确实这样。添加连接选项: /entry:  K5 c, {3 X, ?$ f
main,把入口地址直接指向我们的main函数看看。得到592Bytes。
3 H4 D5 o- S+ [' K# N
2 r6 r0 T" C7 ~! V! j! Z最终我们得到我们最后的大小592Bytes了。我想这也许是我们通过编译器能够编译& b" {, }9 U4 {( A
出来的最小的代码了。
. Q1 P0 A: |5 d& M4 t+ J$ z) P) r3 H& I! B1 f1 }
结论:
# s7 `; m  v9 M  y3 c通过上述的步骤,我们了解了如何修改那些编译连接选项来达到执行文件瘦身的目) @! I+ L. `! d* B% E
的。但是,通常来讲,在我们的Release文件当中,并不需要如此小的执行文件。
0 u6 x# F, C; a) e如果想达到瘦身的目的,修改为library:MutiThreaded Dll和添加/opt:nowin98已
+ k( m+ a5 u0 U* V( M# R7 f1 H经是很好的选择了。其他别的选项在编译的时候或多或少的有警告出现,而且,带
  N6 [/ u' v0 G! H有那些编译选项编出来的执行文件也不一定在各个平台上能够适用。9 H. u/ a4 A: Y/ d. O( W0 q

* R8 ~9 G8 F9 W5 k; p7 N: f另外:如果你的执行文件即使通过了这些设定还是比较大的话,也可以通过一些3 l* E  Z9 s9 W7 g) i5 E
EXE文件压缩工具来进行压缩。比如UPX等等。在此不再细说了。
& x5 `4 f5 d3 b+ S3 o. f, J* c
$ X# o$ ?# O0 I* T以上部分的不足之处,还请多多指正。
发表于 2006-10-3 13:00:07 | 显示全部楼层
谢谢楼主
回复

使用道具 举报

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

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-9-5 14:57 , Processed in 0.014644 second(s), 4 queries , Redis On.

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

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