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

瘦身你的执行文件

[复制链接]
发表于 2006-9-28 21:36:19 | 显示全部楼层 |阅读模式
在网上,有好多绿色软件,不仅功能强大,而且软件本身的体积非常小。有的通常
+ ?  ^0 K. m1 g# j3 O3 B9 n只在几十K左右。那他们是怎么做到把软件做的怎么小的呢?现在我手把手的告诉+ s% I0 h; r4 n. H' W# v- l
你如何通过修改程序的编译选项来瘦身你的执行文件
7 V) ^) a  ?# M& i9 }% B先看一个最典型的程序:
, r2 y2 a  x' [) y#include<stdio.h>
( l* e6 C9 b) hint main()
0 W# ^: v/ a! \3 f5 V{
* Q* K, D/ b3 m- r0 e: Q0 w printf("Hello,World");5 f  L0 W, q$ j# E" O& N6 `- M
return 0;
: d1 r0 |: p5 ~$ y% o}( t) c  o: V$ [5 ~
  K$ Y& r$ u* a) Q
上面的程序之所以被称之为典型,是因为他有如下的内容:
+ k  d) v) q- y1 J" M0 W1、系统函数调用:printf
0 t% x% Y4 x, V) L6 W, i2、有静态数据段
5 i/ T. n! G8 t. M* p; x4 |3 c* h% o" X& [3 S/ i# u
好,现在把此文件放到VisualStudio6.0中进行编译,看看文件有多大。
, X: u* g7 A9 J) h1、用VisualStudio6.0打开HelloWorld.cpp文件,直接按F7。然后点击OK,生成
- E0 a# H9 O  a. f6 j+ P4 yProject文件,然后进行编译。编译完成了以后,看看Debug目录下的执行文件的大8 b" y% @5 l$ ?- @6 U  U
小,为172,096Bytes。9 I, o/ W7 W# p1 G; ~

3 ^6 s. @! k, b/ v9 J6 ]! R2、刚才编译的Debug文件,现在修改成Release文件看看。选择Win32 Release,再% x' {3 J, D: w- d
编译。察看执行文件大小,现在成了40,960Bytes。看来Debug版本的要比Release
3 W' H( a: l1 L  \! |0 I的小。
7 V0 y& T$ E, Y. {
1 G4 O6 E# A" i3、检查代码优化:发现执行文件的优化是Maximize Speed。那么修改成Minimize
! a/ u' E0 n; z; w6 r7 o, E5 kSize看看。重新编译,得到执行文件的大小为:40,960Bytes。看来大小没什么变: x. V4 ?! ?+ I; N
化。其实这是由于我们的代码本身太小的缘故,导致即使变化了也看不出来。. _2 A0 i7 g2 Q. k! F0 D7 k$ a9 X

0 b7 E3 ~: l& \; N2 L2 l4、想想我们程序的main函数是由CRT类库进行引导的。在我们现在的设定当中,由
7 A5 H/ m( S- w( \0 @7 a于采取的是系统缺省的编译连接方式(缺省为编译为Single Thread,Static
7 X( }9 s* x& zLibrary),所以,在我们的执行文件当中,包含了CRT的二进制代码。好,修改编
- S& k0 c4 K  m, x$ P% ~; }译选项:C/C++ => Category:Code Generation => Use run-time" A/ m$ I+ \. S8 V: |& n) u
library:MutiThreaded Dll。编译看看:执行文件大小变成了16,384Bytes。
1 e2 D8 t. t& Y) ?5 ?" [( ~- K' Q0 G
, f, c2 Q/ H3 d* R- [2 k5、刚才的设定确实不错,一下子把执行文件大小减小到了16K。现在用UltraEdit0 B. m  }6 a8 ?( i0 a' n
看看执行文件都是些什么内容。结果大吃一惊:基本上都是0。看来这个有减小的
6 D2 `$ w4 l! B5 _+ J& `必要了。都知道,执行文件都有自己的代码段,数据段等等,每个段的大小也是采7 d: f. Y( }, _, M
用编译器缺省设定的。好,我们来修改一下段的大小看看:" E- r1 V% H5 g( J
5.1 连接选项中有一个是/opt:nowin98,意思是将段的大小设定成为Win2000适应  _4 @5 r+ R* l  Q/ F  F! H
的。编译看看:哇塞,变成了2,560byte。看来这个选项确实把文件变小了N多。+ `+ @3 k7 {* |/ b3 p
5.2 在查察连接选项中还有没有什么特别的。发现/align:xx还可以将段大小缩; W) r# {! P9 G5 r$ |( |9 @
小。通过UltraEdit察看刚才/opt:nowin98编译出来的文件,发现每个段的大小都
' u2 u+ |. ]" C; ^. c" a是4K的整数倍。看来/align:xx还有减小的趋势。试一把再说:添加连接选项:1 I1 F6 K) o, G% }' M2 Z0 [
/align:16(这个大小已经是能够设定的最小的了)。看看结果:1,408Bytes。厉* W! f9 H: k" Z% G# U' s# z
害,现在代码更小了。
9 R2 A- H) |+ U/ [. G5.3 现在回想起来,执行文件大小有数据段,执行代码段等等,如果把这些段都合
2 Z* [% W5 G" V  i  ^并起来,是不是就会把段之间的冗余有减小了呢?再试试看:添加选项:' @- [$ C; ?% j& K. o9 N* W+ A
/merge:.data=.text /merge:.rdata=.text。再看看文件大小:1,328bytes。真的. y% o4 m+ h. N6 b# l) G
很不错了。
; }- d) G8 o0 ]+ k6 Z0 Q
; u3 e5 S4 ]: H6 Z6、刚才的设定确实不错,似乎达到了我们想要的极限了。但是回头想一下,如果& u) U& b% w1 S* y
没有CRT库的话,会不会更小了?实际上确实这样。添加连接选项: /entry:
6 D% q- }' x2 N8 umain,把入口地址直接指向我们的main函数看看。得到592Bytes。
8 n+ Z! T5 z0 C0 T5 W6 P/ S- x2 o) m% t% e: m7 M5 h
最终我们得到我们最后的大小592Bytes了。我想这也许是我们通过编译器能够编译- s8 I3 F2 w) A4 ?' O
出来的最小的代码了。
! Y% J: E# r, M) @0 j2 a& I
  _6 W. {7 c& o结论:# k$ a3 t5 F  o& \
通过上述的步骤,我们了解了如何修改那些编译连接选项来达到执行文件瘦身的目' q6 ]( a. U+ Y8 Z( r* Z
的。但是,通常来讲,在我们的Release文件当中,并不需要如此小的执行文件。
6 H- L: E; j- \% F# h9 {如果想达到瘦身的目的,修改为library:MutiThreaded Dll和添加/opt:nowin98已, S4 ]2 ^5 i' d6 B. W+ b1 F
经是很好的选择了。其他别的选项在编译的时候或多或少的有警告出现,而且,带2 L8 b8 \- z% I% P; e
有那些编译选项编出来的执行文件也不一定在各个平台上能够适用。
. _; x  D' h3 g1 L+ T$ A& Q; v8 j* u. y6 h
另外:如果你的执行文件即使通过了这些设定还是比较大的话,也可以通过一些/ s/ j+ c3 E+ n: y$ r; x
EXE文件压缩工具来进行压缩。比如UPX等等。在此不再细说了。
5 n4 u& t# |4 f6 X. b7 ^7 ~& ~
5 [) X  w5 y# N以上部分的不足之处,还请多多指正。
发表于 2006-10-3 13:00:07 | 显示全部楼层
谢谢楼主
回复

使用道具 举报

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

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-12-20 23:09 , Processed in 0.053609 second(s), 5 queries , Redis On.

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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