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

瘦身你的执行文件

[复制链接]
发表于 2006-9-28 21:36:19 | 显示全部楼层 |阅读模式
在网上,有好多绿色软件,不仅功能强大,而且软件本身的体积非常小。有的通常
( _5 n7 A" w; J; B- }4 L只在几十K左右。那他们是怎么做到把软件做的怎么小的呢?现在我手把手的告诉
: c' p% j8 B/ f5 x  o6 e& @你如何通过修改程序的编译选项来瘦身你的执行文件- @3 ]- r0 _1 x* C
先看一个最典型的程序: 0 P/ X. n$ H! f* W0 w( }, n, A
#include<stdio.h>
8 B4 L! p& q+ P* U0 E7 }int main()
* Z- }) z! d6 V9 {* d# H4 m, U{9 o: k1 \, C0 a8 [. r) O
printf("Hello,World");
3 K$ Y& o  b0 P& J9 b' J return 0;4 w( s' B2 w5 a6 r: ]  ^
}9 ^1 G# S5 M, U6 b) G; P7 |
% I0 a3 G' y$ R
上面的程序之所以被称之为典型,是因为他有如下的内容:9 U% X6 S4 E+ u- I
1、系统函数调用:printf
9 V3 }& S0 T& l5 p8 |( {2、有静态数据段
" o- ^$ R* U2 S& C( E( u3 K+ a/ C% {; K5 \3 z) T* [% v/ [1 W
好,现在把此文件放到VisualStudio6.0中进行编译,看看文件有多大。
( _4 k  L  x* Y, ]+ Q1、用VisualStudio6.0打开HelloWorld.cpp文件,直接按F7。然后点击OK,生成
7 g1 `% Q/ ^5 u- B# z' ^# s/ n0 \6 rProject文件,然后进行编译。编译完成了以后,看看Debug目录下的执行文件的大
+ C# u) ]+ m/ }+ J2 ?/ {1 B小,为172,096Bytes。$ W( w) N; J5 K- ~% T) ]7 ^4 L

0 v) d" f2 i( K9 i9 s2、刚才编译的Debug文件,现在修改成Release文件看看。选择Win32 Release,再, |6 a# C6 _# i- ?4 B6 |
编译。察看执行文件大小,现在成了40,960Bytes。看来Debug版本的要比Release
. S7 P2 u; `: N* [7 V8 a0 j的小。
: _2 p$ V6 G+ C- D/ F) ]0 {+ B4 }" |( N% H! f
3、检查代码优化:发现执行文件的优化是Maximize Speed。那么修改成Minimize2 l" t! f  N" W5 t% F
Size看看。重新编译,得到执行文件的大小为:40,960Bytes。看来大小没什么变( t+ B7 O8 R/ l3 x+ f4 x1 y
化。其实这是由于我们的代码本身太小的缘故,导致即使变化了也看不出来。
; k& x* A' q( H, z
4 R. `/ A. i; @$ B4、想想我们程序的main函数是由CRT类库进行引导的。在我们现在的设定当中,由
5 A. K- c8 L; ?3 |+ x于采取的是系统缺省的编译连接方式(缺省为编译为Single Thread,Static
0 j1 \9 J) E: C/ zLibrary),所以,在我们的执行文件当中,包含了CRT的二进制代码。好,修改编
" Z7 L) b$ f& |; u. E译选项:C/C++ => Category:Code Generation => Use run-time
" j/ q& |0 O7 |2 x2 c0 k! Wlibrary:MutiThreaded Dll。编译看看:执行文件大小变成了16,384Bytes。
6 E' I; Z6 W6 W" y* A: e6 h
4 t# |& N2 M! t2 k! h* K5、刚才的设定确实不错,一下子把执行文件大小减小到了16K。现在用UltraEdit
/ {9 L6 e! N4 V0 @4 q看看执行文件都是些什么内容。结果大吃一惊:基本上都是0。看来这个有减小的
, H3 k  q# {$ ]1 ^' F! F0 P必要了。都知道,执行文件都有自己的代码段,数据段等等,每个段的大小也是采, g& }/ ~' w1 }; ]! E
用编译器缺省设定的。好,我们来修改一下段的大小看看:
# o2 L  u& T: f' }5.1 连接选项中有一个是/opt:nowin98,意思是将段的大小设定成为Win2000适应- [; x3 l8 Y, `
的。编译看看:哇塞,变成了2,560byte。看来这个选项确实把文件变小了N多。$ C) s9 M9 P5 `! l; G8 I
5.2 在查察连接选项中还有没有什么特别的。发现/align:xx还可以将段大小缩
& j% Z- O' r) Q$ y小。通过UltraEdit察看刚才/opt:nowin98编译出来的文件,发现每个段的大小都
2 }- b* t5 }: m/ B6 h是4K的整数倍。看来/align:xx还有减小的趋势。试一把再说:添加连接选项:4 H) E  q% H% r# v' v
/align:16(这个大小已经是能够设定的最小的了)。看看结果:1,408Bytes。厉
5 T3 \. J) ]* y8 r* M: O6 W! W1 m5 k% B害,现在代码更小了。
# M/ m- b- T8 y! X+ i5.3 现在回想起来,执行文件大小有数据段,执行代码段等等,如果把这些段都合
0 k* H$ u+ @9 T) Z# Q并起来,是不是就会把段之间的冗余有减小了呢?再试试看:添加选项:
# q4 H5 [( X" c+ o' Z/merge:.data=.text /merge:.rdata=.text。再看看文件大小:1,328bytes。真的
$ S! C' r" k) O* {- C- }很不错了。, b- @6 i9 t+ |4 Z9 |; Q" j
" ^% I4 x3 q  q$ B; D3 M( Z
6、刚才的设定确实不错,似乎达到了我们想要的极限了。但是回头想一下,如果
6 p2 g0 m' E1 C! z) _没有CRT库的话,会不会更小了?实际上确实这样。添加连接选项: /entry:& A8 h. U4 R0 L1 r; V
main,把入口地址直接指向我们的main函数看看。得到592Bytes。
2 Z! {) e0 L* x* N: F: p9 V+ `) L% T- h8 k( O
最终我们得到我们最后的大小592Bytes了。我想这也许是我们通过编译器能够编译1 r5 Q. I3 |$ z- x" m+ [
出来的最小的代码了。% J# `3 A; |6 I7 x

" ~! ?1 H, b! r' p结论:
, O' P5 C; F/ J" l: B通过上述的步骤,我们了解了如何修改那些编译连接选项来达到执行文件瘦身的目
. _; V# T; I. z2 r的。但是,通常来讲,在我们的Release文件当中,并不需要如此小的执行文件。
/ R0 b6 D% a! \9 f如果想达到瘦身的目的,修改为library:MutiThreaded Dll和添加/opt:nowin98已+ y4 h  i( g$ d! J& x5 a! J
经是很好的选择了。其他别的选项在编译的时候或多或少的有警告出现,而且,带
  i- I2 E4 K: @( D! _有那些编译选项编出来的执行文件也不一定在各个平台上能够适用。
+ \' {6 z) U1 h$ D9 u7 I( @' Z2 Y0 f* m- D. i- p% o' S# V9 Z
另外:如果你的执行文件即使通过了这些设定还是比较大的话,也可以通过一些; U, s; s! U7 g. K+ m5 V
EXE文件压缩工具来进行压缩。比如UPX等等。在此不再细说了。3 G* N" f5 k7 ]4 n" f/ K
9 N( X, M# _7 ?8 z& E
以上部分的不足之处,还请多多指正。
发表于 2006-10-3 13:00:07 | 显示全部楼层
谢谢楼主
回复

使用道具 举报

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

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-7-19 10:23 , Processed in 0.059906 second(s), 5 queries , Redis On.

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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