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

瘦身你的执行文件

[复制链接]
发表于 2006-9-28 21:36:19 | 显示全部楼层 |阅读模式
在网上,有好多绿色软件,不仅功能强大,而且软件本身的体积非常小。有的通常
6 |) F" k1 R3 w% j  m* |只在几十K左右。那他们是怎么做到把软件做的怎么小的呢?现在我手把手的告诉
8 Z1 V0 Y9 \3 J( I4 ~你如何通过修改程序的编译选项来瘦身你的执行文件
4 l1 r2 U+ ]- k4 {! b, r, ?2 R先看一个最典型的程序: / C/ Q& ^3 k0 e$ C8 `2 i
#include<stdio.h>! k: E) w# I$ X3 S' P& t3 v4 [
int main()' c  c, L( p9 S
{7 {3 M# R! x& B9 P7 c" E) o9 m4 P
printf("Hello,World");
' g8 R8 U' G% n# E! i return 0;
9 A& `- R3 u9 L; k- U* z1 m}
/ x% T. q9 P) r* X2 [4 `" i/ s- v2 N" y7 p, X4 T
上面的程序之所以被称之为典型,是因为他有如下的内容:" C1 V- @8 y! g6 v
1、系统函数调用:printf/ X) y( U% T; S
2、有静态数据段* W# F3 y) w, u6 y; T

' M; y- j2 t& f' h8 l# g' k好,现在把此文件放到VisualStudio6.0中进行编译,看看文件有多大。
% F) [: V1 i- u, T2 Q) u$ \1、用VisualStudio6.0打开HelloWorld.cpp文件,直接按F7。然后点击OK,生成% A( ^, I* K4 ]5 E
Project文件,然后进行编译。编译完成了以后,看看Debug目录下的执行文件的大1 C7 G  \& ~6 w2 h
小,为172,096Bytes。
, p2 B, P4 `' \1 P& g6 I! W+ Y& t- l+ A2 ~
2、刚才编译的Debug文件,现在修改成Release文件看看。选择Win32 Release,再: X9 p7 N6 H6 O; m' ~% v, u
编译。察看执行文件大小,现在成了40,960Bytes。看来Debug版本的要比Release
9 y! U3 ^, O) s$ L4 m8 M* I$ V8 {, Z的小。
: `2 S3 \( \. B0 l5 \* @  M9 Z* b, f5 n2 ^6 ^% S* s& W
3、检查代码优化:发现执行文件的优化是Maximize Speed。那么修改成Minimize
1 a, ^$ R. ?3 y. Y( b5 h2 R4 G, BSize看看。重新编译,得到执行文件的大小为:40,960Bytes。看来大小没什么变. `+ P; ^. l& o
化。其实这是由于我们的代码本身太小的缘故,导致即使变化了也看不出来。/ B8 ]+ \3 S0 e0 A% L

8 n3 W" a4 l0 k7 g6 V: a3 F- e4、想想我们程序的main函数是由CRT类库进行引导的。在我们现在的设定当中,由
* ?/ }  N4 t% P" p1 B于采取的是系统缺省的编译连接方式(缺省为编译为Single Thread,Static1 P7 }+ v0 Z2 O: `& u: g
Library),所以,在我们的执行文件当中,包含了CRT的二进制代码。好,修改编3 p  N0 G3 ]& O9 |( A7 ^& {1 [
译选项:C/C++ => Category:Code Generation => Use run-time
5 p1 ^( X1 V3 y# C! f1 _) nlibrary:MutiThreaded Dll。编译看看:执行文件大小变成了16,384Bytes。7 T$ n! U( x7 v0 W1 _) O

. P. E# z% I1 ^+ `' O5、刚才的设定确实不错,一下子把执行文件大小减小到了16K。现在用UltraEdit
# E0 a8 E' s- T, I看看执行文件都是些什么内容。结果大吃一惊:基本上都是0。看来这个有减小的% n9 D. \% f" F6 v0 q
必要了。都知道,执行文件都有自己的代码段,数据段等等,每个段的大小也是采$ y3 i" P: F6 P9 p; j# d" p$ D' T  \
用编译器缺省设定的。好,我们来修改一下段的大小看看:
! H/ [: \' `$ U5.1 连接选项中有一个是/opt:nowin98,意思是将段的大小设定成为Win2000适应" ]" B2 m9 P7 j7 v
的。编译看看:哇塞,变成了2,560byte。看来这个选项确实把文件变小了N多。
) y# V: d9 x. b; ?5.2 在查察连接选项中还有没有什么特别的。发现/align:xx还可以将段大小缩
/ O0 H. l3 R0 n4 B. u" C# Z小。通过UltraEdit察看刚才/opt:nowin98编译出来的文件,发现每个段的大小都+ E1 X# E# s6 _: a  T
是4K的整数倍。看来/align:xx还有减小的趋势。试一把再说:添加连接选项:3 b5 U% z8 _; T
/align:16(这个大小已经是能够设定的最小的了)。看看结果:1,408Bytes。厉
0 o. C3 w8 |* k' G% m5 S, M7 U/ L害,现在代码更小了。
5 J" Y0 Q0 h/ }: U: [5.3 现在回想起来,执行文件大小有数据段,执行代码段等等,如果把这些段都合
3 a; ~$ j- Y6 C并起来,是不是就会把段之间的冗余有减小了呢?再试试看:添加选项:
7 e  Z/ s1 _8 _# P' v( a/merge:.data=.text /merge:.rdata=.text。再看看文件大小:1,328bytes。真的
1 o2 {* W' @/ C$ p0 S, G  q  E8 [; y很不错了。7 Z* A+ L# f- {6 s2 d. |
) k% c- a5 m6 |' ]; Y* u
6、刚才的设定确实不错,似乎达到了我们想要的极限了。但是回头想一下,如果' O* Q) A  i+ M0 _# ~2 f; A% c3 |2 }
没有CRT库的话,会不会更小了?实际上确实这样。添加连接选项: /entry:
' q% r1 j6 V% i2 ]) `  k" N! }& wmain,把入口地址直接指向我们的main函数看看。得到592Bytes。1 `: |, d( f& Z' i
6 n6 C9 U( N9 z1 Y3 Y0 I- x+ T# f
最终我们得到我们最后的大小592Bytes了。我想这也许是我们通过编译器能够编译4 C9 \/ G" ^" Y; z$ S9 t& \* ?
出来的最小的代码了。, ~; C! z% [& l) J

0 ]: r( a( M4 x0 D结论:. X' r. @) k; H$ ]$ i6 D
通过上述的步骤,我们了解了如何修改那些编译连接选项来达到执行文件瘦身的目
- ?% v  G5 L7 Y1 r% w$ M6 k的。但是,通常来讲,在我们的Release文件当中,并不需要如此小的执行文件。
( P, S7 ^; b, N- C7 L) d# r如果想达到瘦身的目的,修改为library:MutiThreaded Dll和添加/opt:nowin98已
2 v. D: t( k9 ^' ^; i经是很好的选择了。其他别的选项在编译的时候或多或少的有警告出现,而且,带
, n: c5 w4 E6 {9 G1 E4 |有那些编译选项编出来的执行文件也不一定在各个平台上能够适用。1 R4 Z0 A7 [1 \2 O

$ F1 q/ I' ~0 I' D& Z( F- x5 U( P另外:如果你的执行文件即使通过了这些设定还是比较大的话,也可以通过一些! y. O- f' q  s; S
EXE文件压缩工具来进行压缩。比如UPX等等。在此不再细说了。2 c" o+ I6 q0 v7 g6 |- E

! k; l7 S& d% `* _& q! d以上部分的不足之处,还请多多指正。
发表于 2006-10-3 13:00:07 | 显示全部楼层
谢谢楼主
回复

使用道具 举报

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

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-7-12 15:55 , Processed in 0.052981 second(s), 4 queries , Redis On.

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

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