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

瘦身你的执行文件

[复制链接]
发表于 2006-9-28 21:36:19 | 显示全部楼层 |阅读模式
在网上,有好多绿色软件,不仅功能强大,而且软件本身的体积非常小。有的通常8 n+ L9 N$ [# m% _4 r. f
只在几十K左右。那他们是怎么做到把软件做的怎么小的呢?现在我手把手的告诉
& I- I  H! q6 a" @2 n: h你如何通过修改程序的编译选项来瘦身你的执行文件
" G- N2 J" H# r/ X+ K, {2 y先看一个最典型的程序: $ v- \6 l; `# V& x6 h: d, F
#include<stdio.h>
: V3 h, R0 d+ \2 m/ c& w. {int main()
) Q* u0 [+ a& z# {5 ]7 l0 r9 \{
' W6 \& r5 X! o printf("Hello,World");
0 N  o: Z5 j+ _6 f return 0;# k1 m: s, |1 @8 \/ {1 k/ b, f  q# K
}- i, T) v9 x% J
, I. W3 A2 x- U- z. y
上面的程序之所以被称之为典型,是因为他有如下的内容:
, S3 g# [( r. m7 o4 g1、系统函数调用:printf
2 U' C, |4 ]( @7 ^; J$ N: |2、有静态数据段  Y0 p  n& f! B  i
. K; [: @' L6 d: `& ]4 V
好,现在把此文件放到VisualStudio6.0中进行编译,看看文件有多大。
- c1 I% x: }5 l# z" I1、用VisualStudio6.0打开HelloWorld.cpp文件,直接按F7。然后点击OK,生成
" R6 A9 }& C+ M3 Z8 i: WProject文件,然后进行编译。编译完成了以后,看看Debug目录下的执行文件的大
2 V2 ?% R& y+ S# t; D8 ^6 M1 `! z0 z小,为172,096Bytes。
; a+ B& {, H7 r7 d7 {6 J0 U
$ G1 B, E# _4 J* K7 S3 G2、刚才编译的Debug文件,现在修改成Release文件看看。选择Win32 Release,再
+ N/ F' a% ]  y4 N  Q5 O编译。察看执行文件大小,现在成了40,960Bytes。看来Debug版本的要比Release2 v1 I! S6 S; S" k, g3 d
的小。  u3 O  Z7 m$ b6 w* l4 x

- l; K3 t) b7 K6 p9 |- [; \# p3、检查代码优化:发现执行文件的优化是Maximize Speed。那么修改成Minimize: x  C1 W* h: j+ p1 q4 G
Size看看。重新编译,得到执行文件的大小为:40,960Bytes。看来大小没什么变
1 \% @; q" l% r/ w0 a, l; Y4 C( D化。其实这是由于我们的代码本身太小的缘故,导致即使变化了也看不出来。
; p. u1 o, l1 `9 B" I% q
. W# p: o# {1 w' n% E4、想想我们程序的main函数是由CRT类库进行引导的。在我们现在的设定当中,由9 F- \# O1 U; x# H* z" H
于采取的是系统缺省的编译连接方式(缺省为编译为Single Thread,Static; z# n  w( c- A+ O2 C7 ~9 L* K
Library),所以,在我们的执行文件当中,包含了CRT的二进制代码。好,修改编
: o0 v# _" j! |9 Z0 |4 H译选项:C/C++ => Category:Code Generation => Use run-time5 {" U: `* O& v
library:MutiThreaded Dll。编译看看:执行文件大小变成了16,384Bytes。; i1 L* A1 m$ [
$ P$ f% F- e: z0 j' n! n* L7 r
5、刚才的设定确实不错,一下子把执行文件大小减小到了16K。现在用UltraEdit4 R" f5 X3 B' N+ H( b0 @
看看执行文件都是些什么内容。结果大吃一惊:基本上都是0。看来这个有减小的8 G% N- W4 G* n! L
必要了。都知道,执行文件都有自己的代码段,数据段等等,每个段的大小也是采' t0 A* U- [9 X% c6 g
用编译器缺省设定的。好,我们来修改一下段的大小看看:  r3 C! }; S' }/ ]. |
5.1 连接选项中有一个是/opt:nowin98,意思是将段的大小设定成为Win2000适应- H1 H+ B5 x$ X9 U5 \6 T# J
的。编译看看:哇塞,变成了2,560byte。看来这个选项确实把文件变小了N多。
% b" R/ b( c; W5.2 在查察连接选项中还有没有什么特别的。发现/align:xx还可以将段大小缩1 C: x+ s+ X* x* x* U. V  d( O  u
小。通过UltraEdit察看刚才/opt:nowin98编译出来的文件,发现每个段的大小都: A5 ?. B& A$ {3 D0 g/ ~0 k2 A
是4K的整数倍。看来/align:xx还有减小的趋势。试一把再说:添加连接选项:" n& ]$ r* V0 x+ B
/align:16(这个大小已经是能够设定的最小的了)。看看结果:1,408Bytes。厉
8 V& Y2 f0 H% `( U( Q- H害,现在代码更小了。
1 }/ A( Y1 P  ~, g9 `$ Z& @: w4 ~5.3 现在回想起来,执行文件大小有数据段,执行代码段等等,如果把这些段都合; z, E5 Z: i/ c4 U
并起来,是不是就会把段之间的冗余有减小了呢?再试试看:添加选项:
  H3 y! G. u7 N5 I7 O/merge:.data=.text /merge:.rdata=.text。再看看文件大小:1,328bytes。真的- E3 ?4 G- F5 A4 }* m4 H
很不错了。
! y( v" q# z6 `  a/ G
$ E& E: u& w4 M2 e' q% _6、刚才的设定确实不错,似乎达到了我们想要的极限了。但是回头想一下,如果9 m% j6 R) O! d2 Z' `
没有CRT库的话,会不会更小了?实际上确实这样。添加连接选项: /entry:
/ u5 ?# S* v/ }) ~main,把入口地址直接指向我们的main函数看看。得到592Bytes。
8 O+ F5 y" F3 @8 C1 H" w
! B  F; ]% e' O7 P  m$ G/ i! _最终我们得到我们最后的大小592Bytes了。我想这也许是我们通过编译器能够编译" {+ E" I7 r/ U. l9 c* {# x( `% Y
出来的最小的代码了。
9 c- K! \7 t0 d( J7 P
% D- x7 j8 [- E! j& K结论:) r2 I1 y! L4 _5 `& \+ t& u4 R3 X
通过上述的步骤,我们了解了如何修改那些编译连接选项来达到执行文件瘦身的目1 P" K! |/ q4 C! Q, K, z" R1 x
的。但是,通常来讲,在我们的Release文件当中,并不需要如此小的执行文件。
8 A+ L3 ~: J1 O0 z( \如果想达到瘦身的目的,修改为library:MutiThreaded Dll和添加/opt:nowin98已, j4 y- e* ], o% ]" A+ O
经是很好的选择了。其他别的选项在编译的时候或多或少的有警告出现,而且,带5 v% _+ U/ B+ p5 h$ [2 f  \
有那些编译选项编出来的执行文件也不一定在各个平台上能够适用。+ R' Q0 Y/ A- ^

; J+ D5 }- Q% L! w% H另外:如果你的执行文件即使通过了这些设定还是比较大的话,也可以通过一些
& N8 k2 y- P7 n; G3 T+ ~* eEXE文件压缩工具来进行压缩。比如UPX等等。在此不再细说了。9 L1 ?- ^1 o$ I- b  u8 a% ^9 n
. l; s* [+ b2 _/ b( F! g
以上部分的不足之处,还请多多指正。
发表于 2006-10-3 13:00:07 | 显示全部楼层
谢谢楼主
回复

使用道具 举报

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

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-5-23 05:08 , Processed in 0.123395 second(s), 5 queries , Redis On.

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

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