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

瘦身你的执行文件

[复制链接]
发表于 2006-9-28 21:36:19 | 显示全部楼层 |阅读模式
在网上,有好多绿色软件,不仅功能强大,而且软件本身的体积非常小。有的通常
! t2 N) y& d8 I  j+ M* u只在几十K左右。那他们是怎么做到把软件做的怎么小的呢?现在我手把手的告诉
$ f0 L7 {- K5 K你如何通过修改程序的编译选项来瘦身你的执行文件+ s; {  B& g( i$ ?( v
先看一个最典型的程序: & a+ S, Q$ u* ~: a2 d
#include<stdio.h>
! M' v1 l, ?7 ~7 H0 v% |int main()
% r& q; R4 }  r8 n, Y9 h7 B; i{
/ i: D, T6 {0 u- l& n) N+ j7 n printf("Hello,World");
5 Q4 q. l1 Z$ F+ n/ @+ R  T) ` return 0;9 D& q9 @3 L' n9 {4 `7 P) d
}
" U- V! ^+ H' \* {5 m! J4 A
* q9 S- c# y/ W" {0 ]上面的程序之所以被称之为典型,是因为他有如下的内容:
1 _4 ~/ |/ B# r$ x. ~! N8 O( U1、系统函数调用:printf
9 C" V4 U4 N( Q. @3 ^" F6 P2、有静态数据段
: I  I$ I" I5 w' z  ^, c
; L/ z, P  b. I" s好,现在把此文件放到VisualStudio6.0中进行编译,看看文件有多大。
0 M) q. t. c4 k2 G2 ]8 H# r; Y5 `7 S1、用VisualStudio6.0打开HelloWorld.cpp文件,直接按F7。然后点击OK,生成2 a9 F6 M6 o' N0 N
Project文件,然后进行编译。编译完成了以后,看看Debug目录下的执行文件的大
; f# m) M1 M% u( U3 _小,为172,096Bytes。  F1 _( g, k5 Q: G$ _7 k1 j6 @0 _
, G2 L' S# I& [% [) R4 N
2、刚才编译的Debug文件,现在修改成Release文件看看。选择Win32 Release,再
3 z% f) Y$ ^8 R( d: b' D) `编译。察看执行文件大小,现在成了40,960Bytes。看来Debug版本的要比Release
" o" o, R. \2 F/ f. s9 C! e的小。) e/ {7 V% e* z
- @' {# c  d8 t2 V" X
3、检查代码优化:发现执行文件的优化是Maximize Speed。那么修改成Minimize5 V% e! O9 n5 Y  z2 h$ C
Size看看。重新编译,得到执行文件的大小为:40,960Bytes。看来大小没什么变' q( |: U6 o" ?
化。其实这是由于我们的代码本身太小的缘故,导致即使变化了也看不出来。
& @/ Q  ]3 o. Y, `5 s" |# s
+ i0 [  O% N0 r; C% h( u' h4 F4 y3 V4、想想我们程序的main函数是由CRT类库进行引导的。在我们现在的设定当中,由
0 a0 R, d: F5 Y4 x, o于采取的是系统缺省的编译连接方式(缺省为编译为Single Thread,Static- U7 i4 y' V& w6 b1 z* u; x: s7 l) Y% a
Library),所以,在我们的执行文件当中,包含了CRT的二进制代码。好,修改编& u6 j3 s0 d7 B+ ?
译选项:C/C++ => Category:Code Generation => Use run-time4 x0 i" L1 ^# d  q% D+ e5 Q
library:MutiThreaded Dll。编译看看:执行文件大小变成了16,384Bytes。
: w- q8 o; c* P& ~4 a" N& F  _3 F: ]+ \5 f. o
5、刚才的设定确实不错,一下子把执行文件大小减小到了16K。现在用UltraEdit
, D: H2 z2 j0 f# Z& ~- W看看执行文件都是些什么内容。结果大吃一惊:基本上都是0。看来这个有减小的, S3 [( k2 r- E. T* R- J6 ~
必要了。都知道,执行文件都有自己的代码段,数据段等等,每个段的大小也是采
5 J3 K2 H$ E1 q! ^! i用编译器缺省设定的。好,我们来修改一下段的大小看看:7 e, W& n! u+ Y. P6 W1 |6 f! v
5.1 连接选项中有一个是/opt:nowin98,意思是将段的大小设定成为Win2000适应
- z. T4 v1 Z: t1 z1 J的。编译看看:哇塞,变成了2,560byte。看来这个选项确实把文件变小了N多。
6 x. H4 {, s, Z5.2 在查察连接选项中还有没有什么特别的。发现/align:xx还可以将段大小缩
4 f& r$ g2 A# h6 F小。通过UltraEdit察看刚才/opt:nowin98编译出来的文件,发现每个段的大小都# x2 B; U2 o) K) z5 Y. ?
是4K的整数倍。看来/align:xx还有减小的趋势。试一把再说:添加连接选项:; Q" I9 R7 ~1 ^: L5 {
/align:16(这个大小已经是能够设定的最小的了)。看看结果:1,408Bytes。厉
* P4 K) l% O) f( A害,现在代码更小了。
5 [% ]% ]5 G" i6 R  k$ f5.3 现在回想起来,执行文件大小有数据段,执行代码段等等,如果把这些段都合+ h! A) ?# u9 }" _) |0 ~% ^; O
并起来,是不是就会把段之间的冗余有减小了呢?再试试看:添加选项:; h* a+ C0 n# s& W: ^8 c- M6 k0 E
/merge:.data=.text /merge:.rdata=.text。再看看文件大小:1,328bytes。真的
6 D9 t* p, O2 G. X9 e+ y; f: z很不错了。
: F" C3 k) l/ X+ W( |  @4 O3 a5 I7 V  |: t
6、刚才的设定确实不错,似乎达到了我们想要的极限了。但是回头想一下,如果
) G! O) q7 D# Z3 D, I" [5 N4 |- e没有CRT库的话,会不会更小了?实际上确实这样。添加连接选项: /entry:' l$ z8 u. ?3 U1 C
main,把入口地址直接指向我们的main函数看看。得到592Bytes。
! B& `; v; @+ ^
  z" M$ m. U5 @/ t最终我们得到我们最后的大小592Bytes了。我想这也许是我们通过编译器能够编译
0 X2 Q* t4 j0 J5 |出来的最小的代码了。# z3 `( G( ~8 J: \7 J+ ~
: k/ k0 [) S. H  P2 q0 I( Z
结论:( c8 J$ D- \8 B
通过上述的步骤,我们了解了如何修改那些编译连接选项来达到执行文件瘦身的目& g9 k9 I' g6 e; s2 `9 W$ X0 J& _
的。但是,通常来讲,在我们的Release文件当中,并不需要如此小的执行文件。
' n1 e2 r5 P3 X/ q如果想达到瘦身的目的,修改为library:MutiThreaded Dll和添加/opt:nowin98已9 z2 P2 ?! i: _( Z9 P
经是很好的选择了。其他别的选项在编译的时候或多或少的有警告出现,而且,带8 c( T6 {0 m2 n$ Q+ M
有那些编译选项编出来的执行文件也不一定在各个平台上能够适用。( R% P: X: U; B3 t( v

; T) [2 l$ [; f另外:如果你的执行文件即使通过了这些设定还是比较大的话,也可以通过一些8 R+ \5 i/ H; S+ n
EXE文件压缩工具来进行压缩。比如UPX等等。在此不再细说了。% E7 q& Z9 t7 H8 L
% K- ?. O! C8 s+ k, T1 H
以上部分的不足之处,还请多多指正。
发表于 2006-10-3 13:00:07 | 显示全部楼层
谢谢楼主
回复

使用道具 举报

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

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-6-30 06:07 , Processed in 0.074932 second(s), 4 queries , Redis On.

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

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