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

瘦身你的执行文件

[复制链接]
发表于 2006-9-28 21:36:19 | 显示全部楼层 |阅读模式
在网上,有好多绿色软件,不仅功能强大,而且软件本身的体积非常小。有的通常6 f9 y" w" ^' P6 B3 f
只在几十K左右。那他们是怎么做到把软件做的怎么小的呢?现在我手把手的告诉
  c& s9 z9 f: V7 E, |; L" N; K/ U你如何通过修改程序的编译选项来瘦身你的执行文件
1 G* Y) X% N, p0 B3 B先看一个最典型的程序:
' C+ T7 e) A8 F) y* J#include<stdio.h>
" k; [( C2 `. I7 ?int main()% h# H0 q3 |6 Y( Q0 ?  j; S
{
! J$ `# z2 c; a% t! V- i, W: v printf("Hello,World");& G6 a+ u4 s$ I, W/ |  {. q) l7 o
return 0;9 _! }7 f7 D# w5 a" j3 k+ J0 O- @
}
: L2 Q! \% h$ l4 \2 z' E0 a+ A( C0 B) z% G
上面的程序之所以被称之为典型,是因为他有如下的内容:
  g9 e+ `5 D& S" W8 @1、系统函数调用:printf# a% t8 g0 b# @& e( l' X4 x
2、有静态数据段
1 q4 L. E+ F2 K! K5 Y; @( Z7 j% }6 Q5 |
* R7 b, c, m3 x3 l4 |好,现在把此文件放到VisualStudio6.0中进行编译,看看文件有多大。1 o! |' e! ~5 f; B6 H( k6 o6 N4 }
1、用VisualStudio6.0打开HelloWorld.cpp文件,直接按F7。然后点击OK,生成
2 Y- v  P2 S: `1 ?Project文件,然后进行编译。编译完成了以后,看看Debug目录下的执行文件的大" K) y+ F# F& |* ^% C/ D
小,为172,096Bytes。
4 q( |9 U0 S1 M4 ?! U: j5 w+ R" C
2、刚才编译的Debug文件,现在修改成Release文件看看。选择Win32 Release,再5 ^- h7 F' S! E4 w
编译。察看执行文件大小,现在成了40,960Bytes。看来Debug版本的要比Release
; f4 D& `# ^$ V' i  ]4 j的小。; G$ b9 w" Q8 }6 u) e

( \( s/ M5 ^+ m( B, T3、检查代码优化:发现执行文件的优化是Maximize Speed。那么修改成Minimize& n, z3 d+ h. D
Size看看。重新编译,得到执行文件的大小为:40,960Bytes。看来大小没什么变
6 M7 o) S- [2 h8 f3 f+ d  K; f化。其实这是由于我们的代码本身太小的缘故,导致即使变化了也看不出来。, A& O- o- g+ }# A" G+ _8 b
% C& ?  P: ~* }
4、想想我们程序的main函数是由CRT类库进行引导的。在我们现在的设定当中,由
+ a$ R) P, L" s4 `2 U于采取的是系统缺省的编译连接方式(缺省为编译为Single Thread,Static1 O' `3 m! w7 O6 [: i
Library),所以,在我们的执行文件当中,包含了CRT的二进制代码。好,修改编% @  A' v( S* b) G$ Q# G2 j! i
译选项:C/C++ => Category:Code Generation => Use run-time3 i7 g# e- v1 F/ w* M
library:MutiThreaded Dll。编译看看:执行文件大小变成了16,384Bytes。
( J3 O) y8 }1 ^- y! D' z8 o+ h0 a$ I& k; p" I6 p( \& `: V
5、刚才的设定确实不错,一下子把执行文件大小减小到了16K。现在用UltraEdit
9 o$ z* v5 S  N" x3 s看看执行文件都是些什么内容。结果大吃一惊:基本上都是0。看来这个有减小的
. p# p! \1 C$ f% _: j, ]必要了。都知道,执行文件都有自己的代码段,数据段等等,每个段的大小也是采
% y- i" v9 v, c2 s用编译器缺省设定的。好,我们来修改一下段的大小看看:9 v4 \+ I  j7 R) j; _9 E3 E
5.1 连接选项中有一个是/opt:nowin98,意思是将段的大小设定成为Win2000适应( z5 B. I! L, p3 t8 I
的。编译看看:哇塞,变成了2,560byte。看来这个选项确实把文件变小了N多。
% M/ {5 h! ]4 O- d; E5.2 在查察连接选项中还有没有什么特别的。发现/align:xx还可以将段大小缩
  N! E, Z& o% r小。通过UltraEdit察看刚才/opt:nowin98编译出来的文件,发现每个段的大小都& s) U: m, `1 w
是4K的整数倍。看来/align:xx还有减小的趋势。试一把再说:添加连接选项:) w- h: S8 M# h, M5 L- N
/align:16(这个大小已经是能够设定的最小的了)。看看结果:1,408Bytes。厉. A* z7 ?, A4 X5 I6 I
害,现在代码更小了。
. h7 v( w; X, r/ ]) p5 E) n! c5.3 现在回想起来,执行文件大小有数据段,执行代码段等等,如果把这些段都合
# ?+ N+ G* M1 K1 x并起来,是不是就会把段之间的冗余有减小了呢?再试试看:添加选项:1 A, W" h. u$ E
/merge:.data=.text /merge:.rdata=.text。再看看文件大小:1,328bytes。真的) r8 d; H8 L( R. g: e9 m* w
很不错了。
; B5 |9 ]7 T; ~: O/ y0 r; _- h+ P5 @
6、刚才的设定确实不错,似乎达到了我们想要的极限了。但是回头想一下,如果
: t4 t0 _# k, Q' h) R没有CRT库的话,会不会更小了?实际上确实这样。添加连接选项: /entry:
- G4 q) w8 S4 V1 p3 Q( Wmain,把入口地址直接指向我们的main函数看看。得到592Bytes。' U  I) s; G: A8 m0 i" W

2 J0 t7 r' h% X+ \- Y" P" H最终我们得到我们最后的大小592Bytes了。我想这也许是我们通过编译器能够编译
( R% u$ t  J5 |+ U5 p出来的最小的代码了。+ e! {* R! u" Z) G
1 I/ L1 r5 M* {) z/ H4 Z, S
结论:5 q( k7 I: w6 E. d7 k) Q: W8 j8 _
通过上述的步骤,我们了解了如何修改那些编译连接选项来达到执行文件瘦身的目
( }6 M: |3 a6 T9 ?) s的。但是,通常来讲,在我们的Release文件当中,并不需要如此小的执行文件。# {' K( K7 R& z& |. Z! S/ W; p
如果想达到瘦身的目的,修改为library:MutiThreaded Dll和添加/opt:nowin98已
5 I  ]" j7 u1 E1 E2 C! \6 W经是很好的选择了。其他别的选项在编译的时候或多或少的有警告出现,而且,带6 {- d' z& ^3 N. m! E
有那些编译选项编出来的执行文件也不一定在各个平台上能够适用。
* G- I6 L8 c' n2 [' U" W
. q, E$ U* a3 c1 [" h4 u另外:如果你的执行文件即使通过了这些设定还是比较大的话,也可以通过一些- k* \4 J! U5 p
EXE文件压缩工具来进行压缩。比如UPX等等。在此不再细说了。9 i$ Q6 F* d; r0 E6 Z

3 Y' ]$ U+ u5 |以上部分的不足之处,还请多多指正。
发表于 2006-10-3 13:00:07 | 显示全部楼层
谢谢楼主
回复

使用道具 举报

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

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-6-28 08:06 , Processed in 0.078491 second(s), 5 queries , Redis On.

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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