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

瘦身你的执行文件

[复制链接]
发表于 2006-9-28 21:36:19 | 显示全部楼层 |阅读模式
在网上,有好多绿色软件,不仅功能强大,而且软件本身的体积非常小。有的通常" v( Y( B8 X; O5 I+ ^
只在几十K左右。那他们是怎么做到把软件做的怎么小的呢?现在我手把手的告诉
% r. u( H/ P% A你如何通过修改程序的编译选项来瘦身你的执行文件
; H6 c, F, }9 M( c  e3 D% _7 j! `( J4 z先看一个最典型的程序:
7 V7 y9 H! Y; L#include<stdio.h>* t8 G- I' B, w/ Z& q, j7 \
int main()" O) V3 x  d" }- V0 U2 `
{
- R) T* J6 h! E8 Y: i printf("Hello,World");
, ^, d& d9 D* J. y  ^ return 0;
2 r4 T3 ?' {; F4 r, _}+ f) I+ G  v9 F0 {; j$ Q6 S% F

. V" t0 C$ y2 L, W1 P2 ?) Y上面的程序之所以被称之为典型,是因为他有如下的内容:6 m7 ^+ }/ n# k1 h+ J8 Q4 N
1、系统函数调用:printf7 `/ Q" q" K5 _' o. K1 N6 _
2、有静态数据段* {9 W# J2 }: ^

- M; [( W% i' V$ Y4 N好,现在把此文件放到VisualStudio6.0中进行编译,看看文件有多大。
! c# R. v1 }& l! w! h1、用VisualStudio6.0打开HelloWorld.cpp文件,直接按F7。然后点击OK,生成% _" ~) J% `2 \2 K8 ~
Project文件,然后进行编译。编译完成了以后,看看Debug目录下的执行文件的大) |( k) e0 K6 u8 ]- R' |
小,为172,096Bytes。
4 E/ h/ J* M1 w' v8 @$ S' o# v5 C  C* P9 x6 _& t+ p
2、刚才编译的Debug文件,现在修改成Release文件看看。选择Win32 Release,再. @/ K, a2 I$ h% \  p
编译。察看执行文件大小,现在成了40,960Bytes。看来Debug版本的要比Release
. q2 |6 g& P% ?的小。
- i6 x9 y9 C/ b) m9 M: i2 p  g4 l# n; z- d! ]
3、检查代码优化:发现执行文件的优化是Maximize Speed。那么修改成Minimize
+ E3 F8 M, {: E) M6 W$ vSize看看。重新编译,得到执行文件的大小为:40,960Bytes。看来大小没什么变
% @# m$ v; Y" u5 a$ A- K化。其实这是由于我们的代码本身太小的缘故,导致即使变化了也看不出来。
1 V0 p8 p( _  F
& R7 [) m- B& U, a0 V! z4、想想我们程序的main函数是由CRT类库进行引导的。在我们现在的设定当中,由5 }3 }! }2 v, _# R4 I6 q* n
于采取的是系统缺省的编译连接方式(缺省为编译为Single Thread,Static
& O) Y; a: q. F. BLibrary),所以,在我们的执行文件当中,包含了CRT的二进制代码。好,修改编
2 ^& b% l. {  W! d7 y译选项:C/C++ => Category:Code Generation => Use run-time
# A9 Y7 o$ K% T8 }! w  plibrary:MutiThreaded Dll。编译看看:执行文件大小变成了16,384Bytes。
3 J* A( m1 [2 H3 t! ^5 G; B3 [6 Q5 b$ e( K9 S8 o' ^, T
5、刚才的设定确实不错,一下子把执行文件大小减小到了16K。现在用UltraEdit
- V& z$ I- z8 m+ U3 J" x3 N看看执行文件都是些什么内容。结果大吃一惊:基本上都是0。看来这个有减小的% y2 q0 _- l: G/ h
必要了。都知道,执行文件都有自己的代码段,数据段等等,每个段的大小也是采
$ n7 L) B4 K5 `* c$ h, r用编译器缺省设定的。好,我们来修改一下段的大小看看:
# W; ~! u) P6 s! Y: k: {5.1 连接选项中有一个是/opt:nowin98,意思是将段的大小设定成为Win2000适应
+ }# E6 f9 P/ r' x8 U- j3 m的。编译看看:哇塞,变成了2,560byte。看来这个选项确实把文件变小了N多。
0 z% S5 b' m+ O' i+ O0 ]5.2 在查察连接选项中还有没有什么特别的。发现/align:xx还可以将段大小缩
! z+ J! g, E  E# j/ u$ ^- ^小。通过UltraEdit察看刚才/opt:nowin98编译出来的文件,发现每个段的大小都% {$ A" k% m0 w2 _
是4K的整数倍。看来/align:xx还有减小的趋势。试一把再说:添加连接选项:
5 a9 m2 W! E8 b9 q/align:16(这个大小已经是能够设定的最小的了)。看看结果:1,408Bytes。厉& H$ l- H6 ^1 z8 o6 @4 D* n
害,现在代码更小了。
8 b( S( t+ e& T, y- `" u5.3 现在回想起来,执行文件大小有数据段,执行代码段等等,如果把这些段都合( f8 L3 U8 R! x9 N+ a! n
并起来,是不是就会把段之间的冗余有减小了呢?再试试看:添加选项:( W7 Y6 F* {. b+ a5 q; g3 u; U
/merge:.data=.text /merge:.rdata=.text。再看看文件大小:1,328bytes。真的0 x) u# \7 S' s3 n7 |. b- y$ R
很不错了。
* B' M1 J1 k  h2 @7 n
- w6 p( p, S+ B5 c% `6、刚才的设定确实不错,似乎达到了我们想要的极限了。但是回头想一下,如果
' B( q- q$ D. O# g( z% ^# X没有CRT库的话,会不会更小了?实际上确实这样。添加连接选项: /entry:2 B, q7 P. y2 b  B% H4 D+ }
main,把入口地址直接指向我们的main函数看看。得到592Bytes。
" ^; ~: W8 H# ~- _1 P' S
1 ^8 Q  M6 j6 l3 ~. Z, Q最终我们得到我们最后的大小592Bytes了。我想这也许是我们通过编译器能够编译  ^) L$ N! {$ R  _4 b) c) x, l
出来的最小的代码了。
$ Y+ k7 I  n, H- \9 ?
7 C4 o* J8 b0 N- g6 N% n. J6 T结论:
( I9 G9 D+ g6 X& w: J+ H通过上述的步骤,我们了解了如何修改那些编译连接选项来达到执行文件瘦身的目7 S$ d/ Q. g6 n) ~9 h
的。但是,通常来讲,在我们的Release文件当中,并不需要如此小的执行文件。
5 [1 y. H2 b2 t/ O如果想达到瘦身的目的,修改为library:MutiThreaded Dll和添加/opt:nowin98已
+ v2 U" S( E  @' Q# m经是很好的选择了。其他别的选项在编译的时候或多或少的有警告出现,而且,带
: P" ]7 ?+ k9 }% t8 K! x有那些编译选项编出来的执行文件也不一定在各个平台上能够适用。7 f, U# u8 j/ r' d! F

) F# P  c2 x4 w! Y" R另外:如果你的执行文件即使通过了这些设定还是比较大的话,也可以通过一些
( E9 o* i# L: ]  |% T2 zEXE文件压缩工具来进行压缩。比如UPX等等。在此不再细说了。7 ]% m$ i; T: _9 I5 f

9 F$ \" b. h1 N1 ~* n8 q0 t. H以上部分的不足之处,还请多多指正。
发表于 2006-10-3 13:00:07 | 显示全部楼层
谢谢楼主
回复

使用道具 举报

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

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-7-26 04:12 , Processed in 0.056367 second(s), 5 queries , Redis On.

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

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