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

瘦身你的执行文件

[复制链接]
发表于 2006-9-28 21:36:19 | 显示全部楼层 |阅读模式
在网上,有好多绿色软件,不仅功能强大,而且软件本身的体积非常小。有的通常
- }$ k8 M& `" B( X  t只在几十K左右。那他们是怎么做到把软件做的怎么小的呢?现在我手把手的告诉
2 h. @8 D9 w% D# o& {你如何通过修改程序的编译选项来瘦身你的执行文件
% {. m$ L/ `) {' E+ n$ [先看一个最典型的程序: 1 n5 v6 k# l6 p- k" D- y- V1 ?
#include<stdio.h>
( q5 d+ }% g6 n3 ~: P- m* @int main()) D1 @3 b( b# S. g, J
{
4 H0 y) D' c" n, g* s printf("Hello,World");
1 s; N0 I! b" K6 E) D6 y return 0;9 G. P  j5 d% f5 F4 t8 y
}% S/ i) _1 x& Q% y4 B1 H
& F+ M  n- D. U% g
上面的程序之所以被称之为典型,是因为他有如下的内容:# r! H# A1 m* m( s9 A( }/ e2 |
1、系统函数调用:printf
0 b3 p2 q( s# H7 u2、有静态数据段
$ P# y( J1 D! l  j9 k2 X
( q2 I7 e0 {2 L好,现在把此文件放到VisualStudio6.0中进行编译,看看文件有多大。
- i2 U& j( v- k* l1、用VisualStudio6.0打开HelloWorld.cpp文件,直接按F7。然后点击OK,生成
" a; x# @; C$ L8 N. ~  ~2 ]- {Project文件,然后进行编译。编译完成了以后,看看Debug目录下的执行文件的大
7 E1 s# f: ~* B) [% `小,为172,096Bytes。
! E2 D# H! P* v7 E0 @; B2 n( j/ j! Y" {, F- R0 C- G1 Y
2、刚才编译的Debug文件,现在修改成Release文件看看。选择Win32 Release,再& ]' ]5 I. b" o6 u; V* a5 b. W
编译。察看执行文件大小,现在成了40,960Bytes。看来Debug版本的要比Release
$ P7 j+ K& o4 h) X0 M3 W的小。* ^2 a+ f9 K0 D: _+ x

$ [. z* R2 E$ N8 M5 B+ [- [3、检查代码优化:发现执行文件的优化是Maximize Speed。那么修改成Minimize# I  B9 z$ y% K
Size看看。重新编译,得到执行文件的大小为:40,960Bytes。看来大小没什么变) p" W$ D0 u2 P  |# v% |* y
化。其实这是由于我们的代码本身太小的缘故,导致即使变化了也看不出来。0 H+ h% u9 X+ S1 u8 }# e) Z: ]
. y( h; x8 y) k( t, k) X/ ^' J  Y7 Y
4、想想我们程序的main函数是由CRT类库进行引导的。在我们现在的设定当中,由
! K% P7 ?! T. M' o( j于采取的是系统缺省的编译连接方式(缺省为编译为Single Thread,Static5 k% ?9 F7 _9 N
Library),所以,在我们的执行文件当中,包含了CRT的二进制代码。好,修改编* K1 c6 u( t! `2 j
译选项:C/C++ => Category:Code Generation => Use run-time
& k. p  M6 h* F. c, A# `library:MutiThreaded Dll。编译看看:执行文件大小变成了16,384Bytes。0 L; H2 ^2 L! o1 @8 Y/ w

. [+ s4 v4 f. W, g# d, F5、刚才的设定确实不错,一下子把执行文件大小减小到了16K。现在用UltraEdit
( R5 Z5 ]: t3 B看看执行文件都是些什么内容。结果大吃一惊:基本上都是0。看来这个有减小的$ ?: v8 |6 v- G; u
必要了。都知道,执行文件都有自己的代码段,数据段等等,每个段的大小也是采
  I. v% [" Q' P4 A% @, c1 Q$ L用编译器缺省设定的。好,我们来修改一下段的大小看看:+ j3 i0 _3 E4 g- H: v# H! i9 n6 b
5.1 连接选项中有一个是/opt:nowin98,意思是将段的大小设定成为Win2000适应. R" x5 ?$ N0 c5 L/ ^$ V) I( E4 F" B
的。编译看看:哇塞,变成了2,560byte。看来这个选项确实把文件变小了N多。
- K/ T' ?3 t( R; N( Z' z9 z5.2 在查察连接选项中还有没有什么特别的。发现/align:xx还可以将段大小缩
( s3 R* M- u7 O% ~% r% P小。通过UltraEdit察看刚才/opt:nowin98编译出来的文件,发现每个段的大小都
: [4 m% o( i' L3 G9 ]5 Y* q. a& z是4K的整数倍。看来/align:xx还有减小的趋势。试一把再说:添加连接选项:
5 ~/ g+ k  X$ U4 Q. Y/align:16(这个大小已经是能够设定的最小的了)。看看结果:1,408Bytes。厉; H  t/ n" Q. ~1 ^* [& z  w
害,现在代码更小了。
1 q* O8 |/ b$ x/ L" G! \5.3 现在回想起来,执行文件大小有数据段,执行代码段等等,如果把这些段都合
3 E1 h! o, v5 M0 ?& o. g并起来,是不是就会把段之间的冗余有减小了呢?再试试看:添加选项:" |" G& G7 C3 D9 s
/merge:.data=.text /merge:.rdata=.text。再看看文件大小:1,328bytes。真的
5 u) e( H  b7 F很不错了。! b$ a( {: p7 v. ?7 @8 E
# e% U& O& [8 E6 L: P
6、刚才的设定确实不错,似乎达到了我们想要的极限了。但是回头想一下,如果0 x6 N3 w! [8 N8 x# D
没有CRT库的话,会不会更小了?实际上确实这样。添加连接选项: /entry:9 z: x  W7 ?/ N2 f& b5 \' i, A6 C
main,把入口地址直接指向我们的main函数看看。得到592Bytes。
' f9 Y+ }* K- ], e1 S9 Z: Q0 x- a! W; j8 r
最终我们得到我们最后的大小592Bytes了。我想这也许是我们通过编译器能够编译6 e3 x7 j- L) G% W
出来的最小的代码了。& ?( S/ }4 I  I4 Y4 |1 o# k: \

. e$ u( K; c. x8 ^' |" |  f( E结论:6 }2 v, e  S% e9 q& L/ A
通过上述的步骤,我们了解了如何修改那些编译连接选项来达到执行文件瘦身的目
, B6 F2 {/ d& n3 A% t的。但是,通常来讲,在我们的Release文件当中,并不需要如此小的执行文件。
. ]8 ~* H( A3 H, D  s- F3 c如果想达到瘦身的目的,修改为library:MutiThreaded Dll和添加/opt:nowin98已
* j& W8 m" Q, H# S- [经是很好的选择了。其他别的选项在编译的时候或多或少的有警告出现,而且,带# \- J5 O( _0 t  G% P  Y) ~" D0 l
有那些编译选项编出来的执行文件也不一定在各个平台上能够适用。7 K; F8 e8 Q5 ^( R' I

9 u  i6 N0 |" Z- ?0 [' [# w另外:如果你的执行文件即使通过了这些设定还是比较大的话,也可以通过一些' W- |, C2 u2 Q# r2 E( ?: i9 S1 c
EXE文件压缩工具来进行压缩。比如UPX等等。在此不再细说了。
5 x) t$ o2 `3 d6 H% B$ E
) N3 g  k) m* m; D. k6 x' t0 D' |以上部分的不足之处,还请多多指正。
发表于 2006-10-3 13:00:07 | 显示全部楼层
谢谢楼主
回复

使用道具 举报

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

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-8-2 17:11 , Processed in 0.055583 second(s), 4 queries , Redis On.

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

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