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

瘦身你的执行文件

[复制链接]
发表于 2006-9-28 21:36:19 | 显示全部楼层 |阅读模式
在网上,有好多绿色软件,不仅功能强大,而且软件本身的体积非常小。有的通常3 K2 O) V( \. f' Q0 r  h
只在几十K左右。那他们是怎么做到把软件做的怎么小的呢?现在我手把手的告诉1 M% x) x, f; \# x) {
你如何通过修改程序的编译选项来瘦身你的执行文件
9 H. W8 j$ A) j* a9 g# Z  ?4 Q先看一个最典型的程序: . n, A# x! }5 u1 k/ K1 }
#include<stdio.h>. [/ |. K* L0 l7 X$ N- R5 {. L6 Z
int main()
: f( l1 Y9 |  V# N" S. l{
# l0 H# Z7 J: U- P7 n printf("Hello,World");$ Z9 M1 V5 I( k6 Z
return 0;
  V' `# u1 C2 C) O}
8 h+ x. e/ q. w' R' I
- q2 w6 r1 t$ ~' ], t& p" \6 _上面的程序之所以被称之为典型,是因为他有如下的内容:; G3 U; x8 o( q" b
1、系统函数调用:printf$ g; S" T8 h" b/ C$ Z
2、有静态数据段2 j  v7 e- ~/ s, b* x; B8 J

5 s: y7 ?8 }: z  X; y好,现在把此文件放到VisualStudio6.0中进行编译,看看文件有多大。' i9 T1 u3 o, I; L
1、用VisualStudio6.0打开HelloWorld.cpp文件,直接按F7。然后点击OK,生成* T. G" [! l6 q- l
Project文件,然后进行编译。编译完成了以后,看看Debug目录下的执行文件的大1 Z, j/ f8 u& t+ j7 C
小,为172,096Bytes。/ Q  s2 j# q/ {& @: L8 Z

4 G. F# n9 d9 l: ^4 l2、刚才编译的Debug文件,现在修改成Release文件看看。选择Win32 Release,再
' W7 V1 X# h+ p( S' f编译。察看执行文件大小,现在成了40,960Bytes。看来Debug版本的要比Release4 ]$ j2 N4 a* R
的小。
2 w5 a; u/ K2 V, j
/ \* A7 K1 [. L& f6 k3、检查代码优化:发现执行文件的优化是Maximize Speed。那么修改成Minimize8 Y* T/ Q  y+ k* P2 K4 I0 v
Size看看。重新编译,得到执行文件的大小为:40,960Bytes。看来大小没什么变
3 A4 J4 ]- g  Q. [; w+ n. b7 O化。其实这是由于我们的代码本身太小的缘故,导致即使变化了也看不出来。' S$ G% t& b; Q' W' m/ [0 J, v* Q
7 v1 D% M/ Y- s
4、想想我们程序的main函数是由CRT类库进行引导的。在我们现在的设定当中,由5 d8 l* i" ~9 U2 s
于采取的是系统缺省的编译连接方式(缺省为编译为Single Thread,Static) J4 g; f+ X, `- i6 y. R1 d6 r
Library),所以,在我们的执行文件当中,包含了CRT的二进制代码。好,修改编- t7 O) q, c. [2 J3 s
译选项:C/C++ => Category:Code Generation => Use run-time0 m' S: i  L  q( s" |! C" R* }
library:MutiThreaded Dll。编译看看:执行文件大小变成了16,384Bytes。
; K. I% x0 y; O+ [5 f! A) {# Z0 f9 r, X$ w6 L8 k; \
5、刚才的设定确实不错,一下子把执行文件大小减小到了16K。现在用UltraEdit% `) w( @4 a2 X( S4 N9 g9 C; F, i
看看执行文件都是些什么内容。结果大吃一惊:基本上都是0。看来这个有减小的* o6 B6 C8 `, K
必要了。都知道,执行文件都有自己的代码段,数据段等等,每个段的大小也是采. |0 P- W+ R. |' k7 I
用编译器缺省设定的。好,我们来修改一下段的大小看看:, r! O* f  V8 S5 L
5.1 连接选项中有一个是/opt:nowin98,意思是将段的大小设定成为Win2000适应& s& R% X; I) [4 b8 ^+ t
的。编译看看:哇塞,变成了2,560byte。看来这个选项确实把文件变小了N多。) [1 @# [( O# z. j4 A- P
5.2 在查察连接选项中还有没有什么特别的。发现/align:xx还可以将段大小缩# C$ n5 D- m/ A' N" i: ^
小。通过UltraEdit察看刚才/opt:nowin98编译出来的文件,发现每个段的大小都
7 _2 s' t7 Z& w$ M6 P' O是4K的整数倍。看来/align:xx还有减小的趋势。试一把再说:添加连接选项:
5 W; m% A/ Z0 y/align:16(这个大小已经是能够设定的最小的了)。看看结果:1,408Bytes。厉( i: F4 N& v& h
害,现在代码更小了。. L# n9 V1 T4 D8 E# m4 k( Y
5.3 现在回想起来,执行文件大小有数据段,执行代码段等等,如果把这些段都合1 H0 n, n% C6 Y4 c. ?3 ^6 _0 I4 U
并起来,是不是就会把段之间的冗余有减小了呢?再试试看:添加选项:( x% M6 G4 k8 g/ Z; F
/merge:.data=.text /merge:.rdata=.text。再看看文件大小:1,328bytes。真的/ ?) u( p7 w. B7 {* I
很不错了。
9 \# t4 Z: ]# n5 b( E) X+ o. `7 O& f# i$ b  N
6、刚才的设定确实不错,似乎达到了我们想要的极限了。但是回头想一下,如果! }' T  ]' e0 F$ t8 E) U
没有CRT库的话,会不会更小了?实际上确实这样。添加连接选项: /entry:8 g7 b; D- [& {
main,把入口地址直接指向我们的main函数看看。得到592Bytes。( ]0 W. Z( @  w# w# `
" z. k0 {3 x" S1 p9 O; \; ?
最终我们得到我们最后的大小592Bytes了。我想这也许是我们通过编译器能够编译
1 M  d- Y! y: a6 a出来的最小的代码了。8 e! K9 \2 _8 M" H; e# Q5 H) p

6 e$ z0 c# m' \/ ?0 A4 r结论:9 A2 `: r/ m2 O; C/ W
通过上述的步骤,我们了解了如何修改那些编译连接选项来达到执行文件瘦身的目% l/ B4 @1 m/ @! W1 Q0 _
的。但是,通常来讲,在我们的Release文件当中,并不需要如此小的执行文件。
% E7 v, n) Q0 p% W3 S9 o" I8 D* i; [如果想达到瘦身的目的,修改为library:MutiThreaded Dll和添加/opt:nowin98已. ]4 u' }9 H- C
经是很好的选择了。其他别的选项在编译的时候或多或少的有警告出现,而且,带
* `2 W" T! B8 e" `9 J1 m# C有那些编译选项编出来的执行文件也不一定在各个平台上能够适用。
( Y( z2 U5 E  [3 k
2 V2 {. A) X7 N4 J  c另外:如果你的执行文件即使通过了这些设定还是比较大的话,也可以通过一些+ ~( y. D0 M6 D! F9 R3 Q2 k: [/ n
EXE文件压缩工具来进行压缩。比如UPX等等。在此不再细说了。
3 L. L" [! }& w3 d2 x* O3 @* ^( Z6 G7 [$ v
以上部分的不足之处,还请多多指正。
发表于 2006-10-3 13:00:07 | 显示全部楼层
谢谢楼主
回复

使用道具 举报

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

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-8-14 09:28 , Processed in 0.055470 second(s), 5 queries , Redis On.

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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