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

瘦身你的执行文件

[复制链接]
发表于 2006-9-28 21:36:19 | 显示全部楼层 |阅读模式
在网上,有好多绿色软件,不仅功能强大,而且软件本身的体积非常小。有的通常
& y4 R7 I, n- T! d* C* W; Q: Z只在几十K左右。那他们是怎么做到把软件做的怎么小的呢?现在我手把手的告诉- x5 r& z. D9 m# j
你如何通过修改程序的编译选项来瘦身你的执行文件6 e/ {9 Z9 F" }
先看一个最典型的程序: ; }3 B$ f+ ?4 S* p. J+ n
#include<stdio.h>
  r% d/ I, d# r! j) `int main()
' O- U, i# w  g{
- X0 m8 N. V' S1 B printf("Hello,World");
8 r0 w: D( L# P. f) Y return 0;7 \3 ~1 {) ^& s7 F7 g  v6 i
}* o8 C7 H# H' R) u; Q

, n- N! s9 a5 j6 Z上面的程序之所以被称之为典型,是因为他有如下的内容:2 E. u% f/ P7 w, E# e
1、系统函数调用:printf
# @$ h" ?, T% f' m  m' G! L2、有静态数据段
: K( K2 `# i5 \. K0 [1 O7 ?4 m5 i- ~0 I" {% _
好,现在把此文件放到VisualStudio6.0中进行编译,看看文件有多大。
4 ?) y4 ?, c9 z1 ]" `+ e1、用VisualStudio6.0打开HelloWorld.cpp文件,直接按F7。然后点击OK,生成9 S9 ^7 Y1 k& N% n
Project文件,然后进行编译。编译完成了以后,看看Debug目录下的执行文件的大: y- Q* D8 Z) D* i
小,为172,096Bytes。6 \# g) R, I- `; g# O+ |* `/ u

+ Q- b) ?8 ]( B8 U3 f3 q' G2、刚才编译的Debug文件,现在修改成Release文件看看。选择Win32 Release,再
" V* N& h4 A/ D编译。察看执行文件大小,现在成了40,960Bytes。看来Debug版本的要比Release! i8 e: l" k- x% R: K& a
的小。. P' b; }0 ^& l2 D! k* M; ~- i

* P1 T3 \# k* r1 J% t# Z* v6 Y3、检查代码优化:发现执行文件的优化是Maximize Speed。那么修改成Minimize
6 \- Y/ j# V7 w* J) F: g1 WSize看看。重新编译,得到执行文件的大小为:40,960Bytes。看来大小没什么变
/ b1 ~: h6 @$ \; {% O9 `8 a化。其实这是由于我们的代码本身太小的缘故,导致即使变化了也看不出来。
, S( l0 N; f& n: f- Q# c% s' y( x; {5 B$ M
4、想想我们程序的main函数是由CRT类库进行引导的。在我们现在的设定当中,由
, [* O# q/ r; Z0 z+ j! E于采取的是系统缺省的编译连接方式(缺省为编译为Single Thread,Static
. f9 p4 @% X* v1 d9 Y4 @9 {$ }3 aLibrary),所以,在我们的执行文件当中,包含了CRT的二进制代码。好,修改编
+ L6 k  r; ?6 e' `( o: n. S+ Q译选项:C/C++ => Category:Code Generation => Use run-time
& W0 t' N6 G6 c+ _# p8 }library:MutiThreaded Dll。编译看看:执行文件大小变成了16,384Bytes。0 i) Y# g* p" y$ S

. w6 r4 r$ i' Z) y0 V' I: ^# j5、刚才的设定确实不错,一下子把执行文件大小减小到了16K。现在用UltraEdit
, j8 A0 U" T" A, g$ F- q/ z看看执行文件都是些什么内容。结果大吃一惊:基本上都是0。看来这个有减小的
' S# T4 k1 F2 {8 }! e必要了。都知道,执行文件都有自己的代码段,数据段等等,每个段的大小也是采
; B( x! z( ]" P2 X用编译器缺省设定的。好,我们来修改一下段的大小看看:( U- l1 M. b1 b9 N' a- T& a
5.1 连接选项中有一个是/opt:nowin98,意思是将段的大小设定成为Win2000适应! C* w9 S: n+ F; p5 @1 Q6 v
的。编译看看:哇塞,变成了2,560byte。看来这个选项确实把文件变小了N多。: E6 {6 k4 \8 E  J  x. m
5.2 在查察连接选项中还有没有什么特别的。发现/align:xx还可以将段大小缩' C! J, g1 K$ s' w" i
小。通过UltraEdit察看刚才/opt:nowin98编译出来的文件,发现每个段的大小都
. m, y9 v6 a, H  u4 t是4K的整数倍。看来/align:xx还有减小的趋势。试一把再说:添加连接选项:% L# X! J  Y$ A1 W: u8 F
/align:16(这个大小已经是能够设定的最小的了)。看看结果:1,408Bytes。厉, ^" Y% }  \7 S: J
害,现在代码更小了。& x1 t# N5 A# H' y" O9 q8 ^
5.3 现在回想起来,执行文件大小有数据段,执行代码段等等,如果把这些段都合
4 P: Q$ d; X( o+ q; C* @8 d) w+ _并起来,是不是就会把段之间的冗余有减小了呢?再试试看:添加选项:
* A! C9 X* a, A+ U% t# {/merge:.data=.text /merge:.rdata=.text。再看看文件大小:1,328bytes。真的  w! v( x5 }( t: D) M/ D: e
很不错了。
" `- r. b. S2 l( t1 V% J( h3 l' N5 r8 o1 o  m+ t. p$ j5 P& }4 K
6、刚才的设定确实不错,似乎达到了我们想要的极限了。但是回头想一下,如果
1 {( J9 t/ I, w- _- i& ~没有CRT库的话,会不会更小了?实际上确实这样。添加连接选项: /entry:
2 {5 ~1 ?+ w! c8 U1 Rmain,把入口地址直接指向我们的main函数看看。得到592Bytes。6 C: P3 K1 l# B; ?" ~% H: D
* Y  Z5 s+ H+ J( D8 e' h, m
最终我们得到我们最后的大小592Bytes了。我想这也许是我们通过编译器能够编译4 f& b+ H& u. h) S: P- a' _
出来的最小的代码了。
8 j/ G3 P( X" B; H+ Y' G. b+ @6 ?/ i- }; _% I
结论:
0 E" a# ^, s5 H# y通过上述的步骤,我们了解了如何修改那些编译连接选项来达到执行文件瘦身的目1 o3 m* l$ z2 [/ w& U9 v: i* B. j
的。但是,通常来讲,在我们的Release文件当中,并不需要如此小的执行文件。
. u: m1 x+ v4 r如果想达到瘦身的目的,修改为library:MutiThreaded Dll和添加/opt:nowin98已
. x0 W% {" l  {6 {/ e; r经是很好的选择了。其他别的选项在编译的时候或多或少的有警告出现,而且,带' z# L  O5 u, N- g! M4 q- {  H
有那些编译选项编出来的执行文件也不一定在各个平台上能够适用。0 S; j! O2 Q1 `1 l9 u
" Y, h# Z5 m( E) E
另外:如果你的执行文件即使通过了这些设定还是比较大的话,也可以通过一些% K$ _' `) H, G* s
EXE文件压缩工具来进行压缩。比如UPX等等。在此不再细说了。) j  \4 |5 [" t4 I$ k1 s

* M  R/ j. o  w) ^. {7 `以上部分的不足之处,还请多多指正。
发表于 2006-10-3 13:00:07 | 显示全部楼层
谢谢楼主
回复

使用道具 举报

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

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-6-23 18:08 , Processed in 0.056183 second(s), 4 queries , Redis On.

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

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