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

瘦身你的执行文件

[复制链接]
发表于 2006-9-28 21:36:19 | 显示全部楼层 |阅读模式
在网上,有好多绿色软件,不仅功能强大,而且软件本身的体积非常小。有的通常- ]( `: V- S2 c- ~# z. b7 v+ L
只在几十K左右。那他们是怎么做到把软件做的怎么小的呢?现在我手把手的告诉
" L5 N" b3 }6 ~0 Z, X; J你如何通过修改程序的编译选项来瘦身你的执行文件* N/ a$ K8 \9 C" V' B8 Y! I
先看一个最典型的程序:
5 t/ {+ h+ p3 Z- q9 ]( Q8 }: w- {#include<stdio.h>; [9 G+ P) \2 O
int main(). ~. G' j" S( P" u* N
{3 [4 X+ K, q/ q. g- C. J9 ~
printf("Hello,World");9 N) L! N3 @* w' u: A
return 0;
. F( l9 D7 t0 J. _0 f9 r}
8 D0 q3 {* |. j& @. D
7 Z, x+ x& d# Z. L; E! o; n上面的程序之所以被称之为典型,是因为他有如下的内容:5 f& q) S$ E" V1 H5 k" Y* q
1、系统函数调用:printf
. z2 G& w3 V$ d# |5 R- a! }5 u" b/ B2、有静态数据段
) N7 ~! `. D0 [9 V- x: D7 j6 H; B9 O4 E3 t$ v
好,现在把此文件放到VisualStudio6.0中进行编译,看看文件有多大。
4 L# s/ ]5 a% y- n: [1、用VisualStudio6.0打开HelloWorld.cpp文件,直接按F7。然后点击OK,生成
- u. F* ~1 N2 b5 q0 ^" M' w, AProject文件,然后进行编译。编译完成了以后,看看Debug目录下的执行文件的大8 Z) ?0 H3 W; q, c) [
小,为172,096Bytes。9 O/ F% R: E/ Q) ]
7 W) l* z# {& g  e+ W3 n; K
2、刚才编译的Debug文件,现在修改成Release文件看看。选择Win32 Release,再
* A# H; `, X: v: E编译。察看执行文件大小,现在成了40,960Bytes。看来Debug版本的要比Release; w/ w  T5 {4 f/ w( z. L. Z
的小。" y& q( \* U5 |, f
7 }% ^9 _# f' G' E2 C9 H
3、检查代码优化:发现执行文件的优化是Maximize Speed。那么修改成Minimize
  t1 H8 p7 v/ B9 Z/ t+ j4 R* q/ MSize看看。重新编译,得到执行文件的大小为:40,960Bytes。看来大小没什么变4 |# {+ h7 F. @
化。其实这是由于我们的代码本身太小的缘故,导致即使变化了也看不出来。, W$ e2 k9 K, ~: G
4 I0 ^8 f2 A6 l, n- T
4、想想我们程序的main函数是由CRT类库进行引导的。在我们现在的设定当中,由
# N3 K/ ?+ [. N于采取的是系统缺省的编译连接方式(缺省为编译为Single Thread,Static
6 P; V# \5 {9 ]5 Q$ h4 J! xLibrary),所以,在我们的执行文件当中,包含了CRT的二进制代码。好,修改编
+ ^/ |& J) H% U' M译选项:C/C++ => Category:Code Generation => Use run-time
" m& ^" ]3 @8 Q9 S8 F& j5 J  ^library:MutiThreaded Dll。编译看看:执行文件大小变成了16,384Bytes。
+ L% }2 n3 w2 e/ J4 B6 B, l# q6 S& W9 `9 R3 E2 w: E7 \8 i
5、刚才的设定确实不错,一下子把执行文件大小减小到了16K。现在用UltraEdit
, e( _( y- G" F# C& C) X7 J看看执行文件都是些什么内容。结果大吃一惊:基本上都是0。看来这个有减小的5 }, T! b; x, S8 m0 i
必要了。都知道,执行文件都有自己的代码段,数据段等等,每个段的大小也是采
; _! w, Z, f* ^9 j5 S2 T用编译器缺省设定的。好,我们来修改一下段的大小看看:
& V  h- }4 ?4 j5.1 连接选项中有一个是/opt:nowin98,意思是将段的大小设定成为Win2000适应  a! U7 t9 P9 o8 Y' }7 \' `# Q
的。编译看看:哇塞,变成了2,560byte。看来这个选项确实把文件变小了N多。3 i3 \  F# ?7 Y/ z" O. b! N4 o( |% q. A
5.2 在查察连接选项中还有没有什么特别的。发现/align:xx还可以将段大小缩
6 y8 q# K5 l( g) B  [小。通过UltraEdit察看刚才/opt:nowin98编译出来的文件,发现每个段的大小都
4 R- G4 |9 ^! U2 w- p, ?是4K的整数倍。看来/align:xx还有减小的趋势。试一把再说:添加连接选项:7 {- r. D$ t) _/ _
/align:16(这个大小已经是能够设定的最小的了)。看看结果:1,408Bytes。厉
. t% P! D2 D6 y: y1 t害,现在代码更小了。! T' @1 ]; N) _8 U
5.3 现在回想起来,执行文件大小有数据段,执行代码段等等,如果把这些段都合1 k2 n  S. p) _! w
并起来,是不是就会把段之间的冗余有减小了呢?再试试看:添加选项:6 m- q8 _' Z9 ^: A2 M/ I, J
/merge:.data=.text /merge:.rdata=.text。再看看文件大小:1,328bytes。真的0 U' \& C/ d! ]8 {3 ~
很不错了。
9 l4 L7 X9 q3 v' |. I  E( Z$ [) n0 G+ g) j- ]- J
6、刚才的设定确实不错,似乎达到了我们想要的极限了。但是回头想一下,如果. ]1 s( c, E! Z1 F6 G% B
没有CRT库的话,会不会更小了?实际上确实这样。添加连接选项: /entry:
1 l5 ^$ n7 z! M2 t/ e+ lmain,把入口地址直接指向我们的main函数看看。得到592Bytes。
% K: {- v9 W0 u
  c/ u! s6 W- v0 A最终我们得到我们最后的大小592Bytes了。我想这也许是我们通过编译器能够编译
/ V. K) a2 X5 x6 X* z7 q. u& a4 T出来的最小的代码了。6 t0 i0 l+ L/ N1 X' g& e, W

# @) k! l( r! N8 i* Z$ W' W结论:. Y/ Y) r2 |3 s3 }, j
通过上述的步骤,我们了解了如何修改那些编译连接选项来达到执行文件瘦身的目
# J$ q7 E/ @/ @的。但是,通常来讲,在我们的Release文件当中,并不需要如此小的执行文件。/ Q) z7 C  E9 B1 k
如果想达到瘦身的目的,修改为library:MutiThreaded Dll和添加/opt:nowin98已
1 W. Y+ w+ X' _$ u4 \* M8 r3 m经是很好的选择了。其他别的选项在编译的时候或多或少的有警告出现,而且,带
* k7 I" X3 P+ |3 r( V有那些编译选项编出来的执行文件也不一定在各个平台上能够适用。6 x! z! b( }5 E! N& u

3 G+ U3 Y, T: J, s另外:如果你的执行文件即使通过了这些设定还是比较大的话,也可以通过一些: F6 X% i! ?. v; n5 s$ D6 R
EXE文件压缩工具来进行压缩。比如UPX等等。在此不再细说了。; O/ ^6 g! K: R% w

# s& \3 H7 }8 ~) N以上部分的不足之处,还请多多指正。
发表于 2006-10-3 13:00:07 | 显示全部楼层
谢谢楼主
回复

使用道具 举报

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

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-2-26 13:21 , Processed in 0.072195 second(s), 5 queries , Redis On.

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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