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

瘦身你的执行文件

[复制链接]
发表于 2006-9-28 21:36:19 | 显示全部楼层 |阅读模式
在网上,有好多绿色软件,不仅功能强大,而且软件本身的体积非常小。有的通常
/ \! G" W1 w* ]3 w3 s  `2 N只在几十K左右。那他们是怎么做到把软件做的怎么小的呢?现在我手把手的告诉: g7 c, n% {- h+ b
你如何通过修改程序的编译选项来瘦身你的执行文件
4 u( y7 g6 \4 Q$ A5 V4 E" `) G& u先看一个最典型的程序: " B. @4 y2 W- x7 d) Z6 h. N3 A
#include<stdio.h>
7 p5 t% O2 P' }; V& B3 _' Aint main()8 L" j; P" M% M2 L3 X$ K- L4 H
{3 J' g. Q% x6 k- i& ^& W  a' Q
printf("Hello,World");2 h6 l9 r# P1 B" y# z$ X# k
return 0;
+ x6 Q' |4 p) B2 Q9 W7 J6 O" O}* o( r5 i4 g; c5 T5 c8 c
6 ?8 L0 w) Z" `& v$ t
上面的程序之所以被称之为典型,是因为他有如下的内容:
2 s3 l9 E: w  k5 O1、系统函数调用:printf& K1 M* `6 R# p5 ], ]
2、有静态数据段
8 @# k0 E1 ^. N5 u% e8 {& U  G# S3 _7 u1 r5 @9 F7 m3 u
好,现在把此文件放到VisualStudio6.0中进行编译,看看文件有多大。- o( {5 z- b) K
1、用VisualStudio6.0打开HelloWorld.cpp文件,直接按F7。然后点击OK,生成
, x4 v/ }9 K2 n5 f  o$ CProject文件,然后进行编译。编译完成了以后,看看Debug目录下的执行文件的大
2 q6 ^4 o' T% j0 x/ D' B+ r8 {0 `小,为172,096Bytes。
5 [, E- G  D2 q" v2 m; O, t, J
2、刚才编译的Debug文件,现在修改成Release文件看看。选择Win32 Release,再
% @( W8 H. y# Q2 {1 U编译。察看执行文件大小,现在成了40,960Bytes。看来Debug版本的要比Release0 _5 q5 M# x7 ?" O6 p& @
的小。
$ n% G* X) r' }- X  o
( \1 B( X% S& Y4 s4 t9 x% y" w2 z3、检查代码优化:发现执行文件的优化是Maximize Speed。那么修改成Minimize
; |/ C& c% Z9 o( R9 iSize看看。重新编译,得到执行文件的大小为:40,960Bytes。看来大小没什么变& C% t- r* y! i. m( I
化。其实这是由于我们的代码本身太小的缘故,导致即使变化了也看不出来。
9 R, M( y0 C3 S1 Y( _; {( K5 A; L* J
4、想想我们程序的main函数是由CRT类库进行引导的。在我们现在的设定当中,由
) E& L! I4 ~4 `- s# ^; l* e8 }于采取的是系统缺省的编译连接方式(缺省为编译为Single Thread,Static
7 p- v  n" R0 K) ]Library),所以,在我们的执行文件当中,包含了CRT的二进制代码。好,修改编1 \6 q& \" D2 `; V" }5 N
译选项:C/C++ => Category:Code Generation => Use run-time
1 r, y  U# p6 K9 P6 P- K; s. hlibrary:MutiThreaded Dll。编译看看:执行文件大小变成了16,384Bytes。, I6 i$ y5 [) Z& t% x0 a3 h+ \

1 j- g4 z  q6 e3 Q& U& ^5、刚才的设定确实不错,一下子把执行文件大小减小到了16K。现在用UltraEdit
2 P; q& N9 m& w- X7 Q看看执行文件都是些什么内容。结果大吃一惊:基本上都是0。看来这个有减小的
, p. J% t- g3 [; s* m3 n必要了。都知道,执行文件都有自己的代码段,数据段等等,每个段的大小也是采1 p- V* `$ v, ?* @: m. c
用编译器缺省设定的。好,我们来修改一下段的大小看看:
6 `: G8 f; f0 j" ^1 D4 q3 x8 j5.1 连接选项中有一个是/opt:nowin98,意思是将段的大小设定成为Win2000适应$ o( p& Y* u- y# @9 q: B- T
的。编译看看:哇塞,变成了2,560byte。看来这个选项确实把文件变小了N多。$ L# q9 a+ I: [- P
5.2 在查察连接选项中还有没有什么特别的。发现/align:xx还可以将段大小缩
: |( n* l# ]0 [* I' x$ v小。通过UltraEdit察看刚才/opt:nowin98编译出来的文件,发现每个段的大小都$ ~6 ^! J' e  q0 H/ I8 f$ k8 d
是4K的整数倍。看来/align:xx还有减小的趋势。试一把再说:添加连接选项:0 R4 Z- P9 x6 t/ D9 N" v
/align:16(这个大小已经是能够设定的最小的了)。看看结果:1,408Bytes。厉
7 \+ W5 H; V  d' D害,现在代码更小了。" X  g' j0 z3 d0 t/ T( |
5.3 现在回想起来,执行文件大小有数据段,执行代码段等等,如果把这些段都合5 f2 \: f: X6 l: H, ^
并起来,是不是就会把段之间的冗余有减小了呢?再试试看:添加选项:
% T+ d, x0 f8 s6 g$ ]/merge:.data=.text /merge:.rdata=.text。再看看文件大小:1,328bytes。真的
% u6 k$ G; f( `$ B) w4 g( D$ e. e很不错了。
* ^' @; Z# {0 @3 _% K, J' n7 r( j
+ E; Q3 C: c* P; C6、刚才的设定确实不错,似乎达到了我们想要的极限了。但是回头想一下,如果
( z! y* [- j5 C% E3 f没有CRT库的话,会不会更小了?实际上确实这样。添加连接选项: /entry:3 N! W  q' N; @& w& E  J
main,把入口地址直接指向我们的main函数看看。得到592Bytes。# _" v; _  ^# F% i  U# Z
7 K* ~% m8 v# P/ x+ C- r  x
最终我们得到我们最后的大小592Bytes了。我想这也许是我们通过编译器能够编译
- j8 {8 H' I# C  N% S7 C出来的最小的代码了。/ D6 g: f9 z# [  x2 G0 q# |! M8 d  U
. v( }; j' Z3 b) @; u: d+ M1 P8 u
结论:6 h- t* x5 @8 o3 z. ]# {
通过上述的步骤,我们了解了如何修改那些编译连接选项来达到执行文件瘦身的目
7 \( N  ~  t* @的。但是,通常来讲,在我们的Release文件当中,并不需要如此小的执行文件。1 N/ ?) z" o4 [
如果想达到瘦身的目的,修改为library:MutiThreaded Dll和添加/opt:nowin98已
6 o% R% K7 w9 b经是很好的选择了。其他别的选项在编译的时候或多或少的有警告出现,而且,带% E6 _0 O! b$ N3 L3 u% c1 {5 W
有那些编译选项编出来的执行文件也不一定在各个平台上能够适用。
1 j9 X) r% d1 E% m' S/ m0 j
( v  L2 S: [3 m2 j' z另外:如果你的执行文件即使通过了这些设定还是比较大的话,也可以通过一些
+ v  T4 N8 B& ]3 z# Y0 KEXE文件压缩工具来进行压缩。比如UPX等等。在此不再细说了。- v( T+ {/ I5 H) X; d' ~; C

: N" p" x& |( S以上部分的不足之处,还请多多指正。
发表于 2006-10-3 13:00:07 | 显示全部楼层
谢谢楼主
回复

使用道具 举报

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

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-5-24 05:04 , Processed in 0.055071 second(s), 5 queries , Redis On.

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

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