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

瘦身你的执行文件

[复制链接]
发表于 2006-9-28 21:36:19 | 显示全部楼层 |阅读模式
在网上,有好多绿色软件,不仅功能强大,而且软件本身的体积非常小。有的通常
3 l, u4 ?$ ?" K0 d. ?# C4 s, Z/ D只在几十K左右。那他们是怎么做到把软件做的怎么小的呢?现在我手把手的告诉
! O" b9 c' k! k& z' c  r$ p2 R, t你如何通过修改程序的编译选项来瘦身你的执行文件
3 O9 }+ d8 ^) @6 H4 z3 P; @先看一个最典型的程序:
; k: O4 F/ t/ G9 E) W% z; Q6 a#include<stdio.h>
9 o. Z8 W: Q- dint main()
+ b- o; t6 j* m- S+ K7 r2 R& w{2 H; j6 ^/ i4 k5 H. ~! m  q" Q
printf("Hello,World");
6 v4 u% s$ i: P6 {4 T return 0;0 x: E; k' _7 q  N
}
* ^: c7 ^  G3 _+ d( y) P7 J/ @* V+ K3 i/ l
上面的程序之所以被称之为典型,是因为他有如下的内容:
: F; b# v/ x- A2 G! C1 ~+ f1、系统函数调用:printf) l" X2 K) k5 s" p) S$ k$ S
2、有静态数据段8 r% `' b- I+ J* }

  f; l( l% s. j好,现在把此文件放到VisualStudio6.0中进行编译,看看文件有多大。
( c$ S- C' T$ \6 J1、用VisualStudio6.0打开HelloWorld.cpp文件,直接按F7。然后点击OK,生成4 S/ ~9 I: j1 w1 @
Project文件,然后进行编译。编译完成了以后,看看Debug目录下的执行文件的大
3 X# P0 G- F& V; B小,为172,096Bytes。
! @3 Q$ t( i) L3 L1 L) S
- r: x% r6 f! l6 M% h, B2、刚才编译的Debug文件,现在修改成Release文件看看。选择Win32 Release,再
$ F" k8 }$ n* G. J4 J0 E3 M编译。察看执行文件大小,现在成了40,960Bytes。看来Debug版本的要比Release' w+ h5 b# m" @3 x4 J- G2 `
的小。1 X; Z- o& V* ?; M

# K! I; H% [* e* z: r3、检查代码优化:发现执行文件的优化是Maximize Speed。那么修改成Minimize7 [! Y- X2 [& n( r; O
Size看看。重新编译,得到执行文件的大小为:40,960Bytes。看来大小没什么变
1 `7 c5 R! }# ~, B. m8 n0 Z# ]化。其实这是由于我们的代码本身太小的缘故,导致即使变化了也看不出来。
& M* `  j$ d  O8 W# Y! Y
' N/ w8 m; \8 H# `3 T4、想想我们程序的main函数是由CRT类库进行引导的。在我们现在的设定当中,由
# ^6 n) t; o1 l! p) u% a2 l于采取的是系统缺省的编译连接方式(缺省为编译为Single Thread,Static0 ^' X, u3 T0 b
Library),所以,在我们的执行文件当中,包含了CRT的二进制代码。好,修改编& n/ i- r4 `' N# t* j3 b; I$ S
译选项:C/C++ => Category:Code Generation => Use run-time
1 H# [/ y& h( x& M( e  Jlibrary:MutiThreaded Dll。编译看看:执行文件大小变成了16,384Bytes。
; Q. o( U: j& ?8 j4 N, s
2 p8 z$ Y/ b9 Y" w0 i5、刚才的设定确实不错,一下子把执行文件大小减小到了16K。现在用UltraEdit
$ k7 q% j; H4 W- j$ Q* h看看执行文件都是些什么内容。结果大吃一惊:基本上都是0。看来这个有减小的+ t/ T2 Y7 G: T4 D( `  U: @* I; o
必要了。都知道,执行文件都有自己的代码段,数据段等等,每个段的大小也是采5 N% z6 Y' L4 g1 z" p! S% T
用编译器缺省设定的。好,我们来修改一下段的大小看看:
0 u3 R; J+ f( ^2 w' \5.1 连接选项中有一个是/opt:nowin98,意思是将段的大小设定成为Win2000适应$ O* m5 m  d# `$ K5 ]
的。编译看看:哇塞,变成了2,560byte。看来这个选项确实把文件变小了N多。0 S2 o6 g  e! r) S) O
5.2 在查察连接选项中还有没有什么特别的。发现/align:xx还可以将段大小缩
+ R7 h8 @% {: s小。通过UltraEdit察看刚才/opt:nowin98编译出来的文件,发现每个段的大小都
1 Z6 M% }6 E1 Z' c! f# G是4K的整数倍。看来/align:xx还有减小的趋势。试一把再说:添加连接选项:" |  s% Q. c, @2 m3 L- o
/align:16(这个大小已经是能够设定的最小的了)。看看结果:1,408Bytes。厉
9 ^' d+ @1 w! q7 |1 j: O$ r害,现在代码更小了。
* K1 c. p8 y3 S( r- l  r5.3 现在回想起来,执行文件大小有数据段,执行代码段等等,如果把这些段都合! y" O" e0 T; C# Q) _
并起来,是不是就会把段之间的冗余有减小了呢?再试试看:添加选项:
: r7 d, m! k" J; b6 G# s/merge:.data=.text /merge:.rdata=.text。再看看文件大小:1,328bytes。真的
. n2 Z6 H* B& m很不错了。& _: v. ]" C0 m# V

5 P* r" H( n5 O7 p6、刚才的设定确实不错,似乎达到了我们想要的极限了。但是回头想一下,如果
& q1 _7 Q3 V/ q% M1 V  r没有CRT库的话,会不会更小了?实际上确实这样。添加连接选项: /entry:
' \: E6 S% P6 Q* v% c! k/ Mmain,把入口地址直接指向我们的main函数看看。得到592Bytes。( M- {" n( h. s( `
/ y: D( U- P. _$ b
最终我们得到我们最后的大小592Bytes了。我想这也许是我们通过编译器能够编译" z1 j% {4 v4 W# N
出来的最小的代码了。
: ], y4 y# X- U6 ?
/ k6 _( y' s' z% F) H0 @2 X结论:
" u# A+ K2 I# o, S通过上述的步骤,我们了解了如何修改那些编译连接选项来达到执行文件瘦身的目
. `# c9 G9 r, e4 H# u的。但是,通常来讲,在我们的Release文件当中,并不需要如此小的执行文件。
/ U6 Y, B/ P# S如果想达到瘦身的目的,修改为library:MutiThreaded Dll和添加/opt:nowin98已0 {* h6 }4 ^7 i
经是很好的选择了。其他别的选项在编译的时候或多或少的有警告出现,而且,带
- P1 T2 E! I6 u( ?有那些编译选项编出来的执行文件也不一定在各个平台上能够适用。
, ?0 q, j: l" l3 m5 y7 F- m4 X6 \0 ?+ n
+ F8 g5 f6 i4 |5 w# v+ ~另外:如果你的执行文件即使通过了这些设定还是比较大的话,也可以通过一些
4 z* s  n/ q5 E" ?- FEXE文件压缩工具来进行压缩。比如UPX等等。在此不再细说了。/ V, G7 r/ x5 J' m6 Y, W

0 p, R6 W9 V/ f- W- b# B以上部分的不足之处,还请多多指正。
发表于 2006-10-3 13:00:07 | 显示全部楼层
谢谢楼主
回复

使用道具 举报

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

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-8-1 11:39 , Processed in 0.052538 second(s), 5 queries , Redis On.

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

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