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

瘦身你的执行文件

[复制链接]
发表于 2006-9-28 21:36:19 | 显示全部楼层 |阅读模式
在网上,有好多绿色软件,不仅功能强大,而且软件本身的体积非常小。有的通常
# Z1 p/ j; P: \3 i6 Q5 [只在几十K左右。那他们是怎么做到把软件做的怎么小的呢?现在我手把手的告诉! q& l# S9 V3 @) B0 \( p% U, Q
你如何通过修改程序的编译选项来瘦身你的执行文件
5 x- U5 {# F# |7 h先看一个最典型的程序:
' n/ K$ R- S- t% p2 v; d# q. G#include<stdio.h>5 D+ j' S$ E/ n
int main(); ^. e2 n. n2 r0 \2 D
{
+ O$ x, c$ Y6 B4 N/ g printf("Hello,World");
- H  n8 K  T5 r6 f& d return 0;
' Y3 t. b! d* F  r0 k}( S! G0 h9 O4 e8 O; ^( e

9 z, B2 S* R5 p# j; O上面的程序之所以被称之为典型,是因为他有如下的内容:$ N* L! V: I  |
1、系统函数调用:printf
& E  s) [0 J" O" Z4 q2、有静态数据段( u; a( f3 o7 [9 z6 [& E

4 U8 Z3 F2 ?& L" [2 Q好,现在把此文件放到VisualStudio6.0中进行编译,看看文件有多大。
6 \, g. C* @8 z3 R( s3 @' C1、用VisualStudio6.0打开HelloWorld.cpp文件,直接按F7。然后点击OK,生成8 o" P, V% T4 ^) Z
Project文件,然后进行编译。编译完成了以后,看看Debug目录下的执行文件的大
( Y. v5 k8 J4 s+ l! h& r小,为172,096Bytes。
$ i4 ]5 {' U/ S8 [
  r8 o0 a# k$ I3 U+ ?. V# D2、刚才编译的Debug文件,现在修改成Release文件看看。选择Win32 Release,再/ A& Y  I2 }: o5 E( H; R( S* K
编译。察看执行文件大小,现在成了40,960Bytes。看来Debug版本的要比Release
$ c  u8 ]& I, k2 p( q的小。
4 ]1 y& u$ t8 `: x
  G' P2 c0 u5 A4 o$ G$ Z3、检查代码优化:发现执行文件的优化是Maximize Speed。那么修改成Minimize
- J) ]3 q. _# D) z& ]2 @  fSize看看。重新编译,得到执行文件的大小为:40,960Bytes。看来大小没什么变$ e* o% H" ]. u& S$ y- N
化。其实这是由于我们的代码本身太小的缘故,导致即使变化了也看不出来。
7 h1 R5 E! C! b# q
. \( K2 n6 Y* J. V3 g1 v8 i" L% ?4、想想我们程序的main函数是由CRT类库进行引导的。在我们现在的设定当中,由8 b7 X; E( N+ c; ~. L$ b! ^
于采取的是系统缺省的编译连接方式(缺省为编译为Single Thread,Static" c; c, Y3 k4 w- q0 _' d
Library),所以,在我们的执行文件当中,包含了CRT的二进制代码。好,修改编' Q6 p8 u: d/ _, b/ g
译选项:C/C++ => Category:Code Generation => Use run-time& n& G& g4 C; Q2 z) @
library:MutiThreaded Dll。编译看看:执行文件大小变成了16,384Bytes。% a5 [  ~! K$ N9 |5 G
7 o* o' W( l  i9 d: }* A
5、刚才的设定确实不错,一下子把执行文件大小减小到了16K。现在用UltraEdit5 j0 _* A9 [% B9 L2 q& U" Y
看看执行文件都是些什么内容。结果大吃一惊:基本上都是0。看来这个有减小的
* Z+ J. u! X7 J7 ^必要了。都知道,执行文件都有自己的代码段,数据段等等,每个段的大小也是采' [2 e( G2 L) Z" I" ^' A
用编译器缺省设定的。好,我们来修改一下段的大小看看:
. a$ ?' K7 m) R) G5 q; X2 ~8 ~5.1 连接选项中有一个是/opt:nowin98,意思是将段的大小设定成为Win2000适应! @* o9 N. n) I: L& v6 U- p
的。编译看看:哇塞,变成了2,560byte。看来这个选项确实把文件变小了N多。; F  R7 h4 y2 K; x
5.2 在查察连接选项中还有没有什么特别的。发现/align:xx还可以将段大小缩
& O; U# O6 n8 c# \2 s小。通过UltraEdit察看刚才/opt:nowin98编译出来的文件,发现每个段的大小都
: B5 s% y8 @) Y. S+ z是4K的整数倍。看来/align:xx还有减小的趋势。试一把再说:添加连接选项:1 J/ H. o' F8 |
/align:16(这个大小已经是能够设定的最小的了)。看看结果:1,408Bytes。厉" [( n: E9 J1 }8 l; B/ D/ z  r4 @7 v! S
害,现在代码更小了。) y3 G; g' f  y7 ]- Z' B
5.3 现在回想起来,执行文件大小有数据段,执行代码段等等,如果把这些段都合) ]( q. L5 n8 g+ ?1 I5 j. }
并起来,是不是就会把段之间的冗余有减小了呢?再试试看:添加选项:. _. D8 L$ b$ D0 N5 ?$ k' W
/merge:.data=.text /merge:.rdata=.text。再看看文件大小:1,328bytes。真的
4 ~5 w$ }) t6 _/ Y, ^1 {+ Q- P  T很不错了。' b) r  ]2 M, k. s1 l
4 [! q' M5 B( V4 H" N
6、刚才的设定确实不错,似乎达到了我们想要的极限了。但是回头想一下,如果) _  P; M6 w; k( C- [) D5 m
没有CRT库的话,会不会更小了?实际上确实这样。添加连接选项: /entry:
8 U! F9 E! [) A% l/ H3 s3 bmain,把入口地址直接指向我们的main函数看看。得到592Bytes。2 w4 H3 X! i# E. ?: T6 G$ u

5 Y; p( b; M- Y% i$ L  q. q& Q- d' |最终我们得到我们最后的大小592Bytes了。我想这也许是我们通过编译器能够编译
7 r! e7 g5 _* y3 g- D出来的最小的代码了。
% v% G3 R4 N! R# Y# X2 l1 D8 u: ?1 K% i9 U/ L. z2 V5 L4 d
结论:% i8 t! q, T0 M5 _
通过上述的步骤,我们了解了如何修改那些编译连接选项来达到执行文件瘦身的目! y( M, C" o* l/ Q
的。但是,通常来讲,在我们的Release文件当中,并不需要如此小的执行文件。  x4 ~  l5 ]5 f+ `  h5 _
如果想达到瘦身的目的,修改为library:MutiThreaded Dll和添加/opt:nowin98已
. q. [  P) D  l- ~7 l经是很好的选择了。其他别的选项在编译的时候或多或少的有警告出现,而且,带7 K. g. U. a2 I' O8 |$ E
有那些编译选项编出来的执行文件也不一定在各个平台上能够适用。: k& _3 I4 F5 g

& e% O8 t8 z; q$ ?另外:如果你的执行文件即使通过了这些设定还是比较大的话,也可以通过一些
% ]7 W! b# U) CEXE文件压缩工具来进行压缩。比如UPX等等。在此不再细说了。
! Q! L0 R& Y. X4 `8 c8 p3 Z+ G5 [! C& g" i  M( N" l% Q9 d+ j
以上部分的不足之处,还请多多指正。
发表于 2006-10-3 13:00:07 | 显示全部楼层
谢谢楼主
回复

使用道具 举报

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

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-8-2 19:45 , Processed in 0.058245 second(s), 4 queries , Redis On.

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

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