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

瘦身你的执行文件

[复制链接]
发表于 2006-9-28 21:36:19 | 显示全部楼层 |阅读模式
在网上,有好多绿色软件,不仅功能强大,而且软件本身的体积非常小。有的通常
9 k, p. o: o; C8 G* e$ ^& I只在几十K左右。那他们是怎么做到把软件做的怎么小的呢?现在我手把手的告诉% A) }& l$ ?8 G8 O3 p) L9 I
你如何通过修改程序的编译选项来瘦身你的执行文件
' w# H8 U: m& R- D0 e& J先看一个最典型的程序:
0 s: `; u3 V, |+ z& u' b9 g#include<stdio.h>
& |( G! h% O: W6 G) ~int main()$ G2 a9 p$ ~: L  G, a" i2 c2 _# d
{
, O' b8 ]3 r0 B" U$ [% E; A; ]5 ] printf("Hello,World");
! M! [- x/ _' q/ y$ b- {+ } return 0;- M9 F( y: c9 ?( D3 f
}
" P* T9 ?. q7 {/ \4 @( |0 T
7 q4 [) b% k. I3 Q上面的程序之所以被称之为典型,是因为他有如下的内容:: o+ v  Z3 m' n* Q6 H  z1 I# D
1、系统函数调用:printf* w. Q6 [4 `# M( K* I$ t  y
2、有静态数据段4 W# Z( ?+ [" p$ n  }+ q
% C: \0 }' v8 ~
好,现在把此文件放到VisualStudio6.0中进行编译,看看文件有多大。0 N( F4 s8 I+ W1 F" [0 b7 U
1、用VisualStudio6.0打开HelloWorld.cpp文件,直接按F7。然后点击OK,生成
6 g- Y! L6 ^3 }- T5 x9 }Project文件,然后进行编译。编译完成了以后,看看Debug目录下的执行文件的大1 |$ T; O' ~, X; D  g
小,为172,096Bytes。+ [* a2 ^3 D# g: B

! R: x/ p3 {5 P  n1 S& U2、刚才编译的Debug文件,现在修改成Release文件看看。选择Win32 Release,再/ J, F( ~9 I. K# A- }- y3 q
编译。察看执行文件大小,现在成了40,960Bytes。看来Debug版本的要比Release
: n# e+ a6 i# J* s( k+ Z的小。
6 P1 x3 a$ q$ l' ], u- T' U$ o
% o5 |+ v" D" n3、检查代码优化:发现执行文件的优化是Maximize Speed。那么修改成Minimize( b% p1 o, W5 ?7 F7 ?4 S0 Y
Size看看。重新编译,得到执行文件的大小为:40,960Bytes。看来大小没什么变2 l! }! c- Z5 _$ {! F; p
化。其实这是由于我们的代码本身太小的缘故,导致即使变化了也看不出来。9 C; U' G0 X% j( k$ y' o8 ]

3 C+ g7 m7 d1 Y  d( t4、想想我们程序的main函数是由CRT类库进行引导的。在我们现在的设定当中,由
; Q) g6 @# H! Z6 t于采取的是系统缺省的编译连接方式(缺省为编译为Single Thread,Static! ^! w+ ~$ f) {+ |7 R8 g' H. f4 ^( d( M
Library),所以,在我们的执行文件当中,包含了CRT的二进制代码。好,修改编
  @% U+ _, I. n. y; o, ~- s6 i7 I3 G译选项:C/C++ => Category:Code Generation => Use run-time9 q$ K* l' }4 ^
library:MutiThreaded Dll。编译看看:执行文件大小变成了16,384Bytes。! ?3 ?1 G4 s0 A8 p  \+ m- ^9 Z1 ]' C9 a

( y) R" o3 m$ Z1 @5、刚才的设定确实不错,一下子把执行文件大小减小到了16K。现在用UltraEdit
: W0 g, h3 w( s" ]2 g% Z5 B看看执行文件都是些什么内容。结果大吃一惊:基本上都是0。看来这个有减小的  y( B$ D" F7 i1 k. ]
必要了。都知道,执行文件都有自己的代码段,数据段等等,每个段的大小也是采
/ _- c# K6 d6 \4 {! F- i+ ]6 Y用编译器缺省设定的。好,我们来修改一下段的大小看看:
+ N  F$ B+ M$ t1 [# D) V5.1 连接选项中有一个是/opt:nowin98,意思是将段的大小设定成为Win2000适应/ ?) E  ^  W/ k. r9 }2 q! ^
的。编译看看:哇塞,变成了2,560byte。看来这个选项确实把文件变小了N多。
8 L+ j, t3 n5 h; \5 F/ z5.2 在查察连接选项中还有没有什么特别的。发现/align:xx还可以将段大小缩
& y' |$ L+ Z0 {; d' B8 }" j小。通过UltraEdit察看刚才/opt:nowin98编译出来的文件,发现每个段的大小都$ N5 b3 `) d5 W8 w: O( P% i; q
是4K的整数倍。看来/align:xx还有减小的趋势。试一把再说:添加连接选项:
, a' E, o' \1 Q; k/align:16(这个大小已经是能够设定的最小的了)。看看结果:1,408Bytes。厉* ~" y- U1 G  C; u
害,现在代码更小了。
( w1 i) [5 N# X* r2 c) c5.3 现在回想起来,执行文件大小有数据段,执行代码段等等,如果把这些段都合
4 b# g0 H& R# K并起来,是不是就会把段之间的冗余有减小了呢?再试试看:添加选项:
0 I/ s# _* B+ F5 {, |3 j& ], ?/merge:.data=.text /merge:.rdata=.text。再看看文件大小:1,328bytes。真的
! C: S7 F  F2 ~5 c; O6 E, I很不错了。
& ~- I, x$ }2 e! b8 K3 C2 D  e' m7 e7 X; _2 L
6、刚才的设定确实不错,似乎达到了我们想要的极限了。但是回头想一下,如果- s7 O5 ^7 ^! `- d, ^" Z( s) G2 r
没有CRT库的话,会不会更小了?实际上确实这样。添加连接选项: /entry:
' w. h  |  M- G8 f8 N; Vmain,把入口地址直接指向我们的main函数看看。得到592Bytes。- X* b" o6 o2 c$ \, \2 q

$ f4 C, a) p0 @# d& L6 F最终我们得到我们最后的大小592Bytes了。我想这也许是我们通过编译器能够编译
- R# V0 r4 g) N5 z! f出来的最小的代码了。0 C  Z4 t3 G2 \0 y  d5 }

$ b8 _6 T- a; Q% Q; e结论:
  @& M6 w2 b" E! E: c通过上述的步骤,我们了解了如何修改那些编译连接选项来达到执行文件瘦身的目# z4 M8 D' p. ]* G- U+ s
的。但是,通常来讲,在我们的Release文件当中,并不需要如此小的执行文件。
. h+ E' ~6 t0 l- w( w' m7 g8 ~如果想达到瘦身的目的,修改为library:MutiThreaded Dll和添加/opt:nowin98已& z4 `- q$ b3 ~; ]) Q
经是很好的选择了。其他别的选项在编译的时候或多或少的有警告出现,而且,带
9 W% k- O, F8 G. f& i6 z有那些编译选项编出来的执行文件也不一定在各个平台上能够适用。
+ i* q3 U) P: b# x: d6 n" ~1 I' Y) B% I) C3 Z3 C% M
另外:如果你的执行文件即使通过了这些设定还是比较大的话,也可以通过一些$ O0 V) v* f% i( K! j
EXE文件压缩工具来进行压缩。比如UPX等等。在此不再细说了。
" W1 w6 N4 `" b% f- H/ D
, w) m# |) S& u8 B, J; u5 J4 j" N以上部分的不足之处,还请多多指正。
发表于 2006-10-3 13:00:07 | 显示全部楼层
谢谢楼主
回复

使用道具 举报

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

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-11-24 16:54 , Processed in 0.062193 second(s), 4 queries , Redis On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

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