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

瘦身你的执行文件

[复制链接]
发表于 2006-9-28 21:36:19 | 显示全部楼层 |阅读模式
在网上,有好多绿色软件,不仅功能强大,而且软件本身的体积非常小。有的通常) H" l' S2 z" Y! E' r
只在几十K左右。那他们是怎么做到把软件做的怎么小的呢?现在我手把手的告诉8 T& B( }- T* K' s7 j
你如何通过修改程序的编译选项来瘦身你的执行文件  [, v; w) `. m+ h. a7 A
先看一个最典型的程序:
2 H1 }9 o2 e! ^/ i% R' B/ E#include<stdio.h>0 t. `3 B+ [7 N1 H
int main()' [) q! m, ?: v* z  @7 R
{) J9 Z& w: T7 v
printf("Hello,World");/ I! r! E" Z( w: I) L
return 0;
3 _2 K. P; A+ `6 g& {}
- h4 k# b# o3 k1 ~7 d/ ^2 V7 v; P, y/ E& ~( j; r
上面的程序之所以被称之为典型,是因为他有如下的内容:! Y6 I" P) Q3 ?( s% w
1、系统函数调用:printf
8 q! |- b6 ^8 {. F0 \# z2、有静态数据段# j( V; m: S  w5 r1 m  L
. b: [5 M' P) o$ s
好,现在把此文件放到VisualStudio6.0中进行编译,看看文件有多大。
5 k% A2 E3 @" Y) Z, ?; C1、用VisualStudio6.0打开HelloWorld.cpp文件,直接按F7。然后点击OK,生成9 z) o- B" F0 y* `2 @
Project文件,然后进行编译。编译完成了以后,看看Debug目录下的执行文件的大: q8 W5 t' T7 n
小,为172,096Bytes。
' }( o! Y0 G# R0 _/ ~4 g6 Q( r5 C" y/ P- b) x2 e+ U, B# }9 |
2、刚才编译的Debug文件,现在修改成Release文件看看。选择Win32 Release,再
# g6 D1 y) N/ _8 Q; R( y# U编译。察看执行文件大小,现在成了40,960Bytes。看来Debug版本的要比Release
2 X+ U" R" G! f2 i的小。
4 k2 R; o/ u4 i$ g+ W& N% X1 A% C/ ?1 Y: Y7 n! ~% [
3、检查代码优化:发现执行文件的优化是Maximize Speed。那么修改成Minimize
5 K4 Q3 N; Y3 Z8 ]  b: xSize看看。重新编译,得到执行文件的大小为:40,960Bytes。看来大小没什么变
+ D1 q. _! W; C' j3 {+ }/ E( W7 n3 F化。其实这是由于我们的代码本身太小的缘故,导致即使变化了也看不出来。
4 q* D2 ?  i$ _+ M( u1 }( J) M" T
" w  @% l% W& S# q" H8 w1 D, i4、想想我们程序的main函数是由CRT类库进行引导的。在我们现在的设定当中,由% g$ K' Y0 z9 w
于采取的是系统缺省的编译连接方式(缺省为编译为Single Thread,Static
0 ?% S4 G' M: j* q& M/ h3 ]Library),所以,在我们的执行文件当中,包含了CRT的二进制代码。好,修改编
: n2 B3 i: a9 g- ?/ p. p; r译选项:C/C++ => Category:Code Generation => Use run-time3 g( y9 R: x9 H3 d3 n  n* V
library:MutiThreaded Dll。编译看看:执行文件大小变成了16,384Bytes。
/ G( e( Q4 @+ c' V* n
  |1 I9 x* m0 p5、刚才的设定确实不错,一下子把执行文件大小减小到了16K。现在用UltraEdit
! U! B! p& B) J" F看看执行文件都是些什么内容。结果大吃一惊:基本上都是0。看来这个有减小的
3 e+ i" A  D- M- Q& @8 [. C必要了。都知道,执行文件都有自己的代码段,数据段等等,每个段的大小也是采
9 w; |" t% @- C  _: p" @% C用编译器缺省设定的。好,我们来修改一下段的大小看看:: S2 P6 {7 v& k: c/ b: P" J
5.1 连接选项中有一个是/opt:nowin98,意思是将段的大小设定成为Win2000适应
  Q$ F+ d; c) g: A6 A: d! o的。编译看看:哇塞,变成了2,560byte。看来这个选项确实把文件变小了N多。
0 Y0 }* {$ K8 g# \0 D# X2 v" O" K! Y4 a5.2 在查察连接选项中还有没有什么特别的。发现/align:xx还可以将段大小缩3 N5 Q% o% g2 L; M; Z& }  z
小。通过UltraEdit察看刚才/opt:nowin98编译出来的文件,发现每个段的大小都' v" Q- O$ E% C$ t; U; @7 N7 P4 y
是4K的整数倍。看来/align:xx还有减小的趋势。试一把再说:添加连接选项:
& P) F1 N0 {* p/align:16(这个大小已经是能够设定的最小的了)。看看结果:1,408Bytes。厉9 ~: u5 U1 @- v* [$ W+ [( J& h! l
害,现在代码更小了。
9 B! c4 I7 g: v5 i4 T5 O5.3 现在回想起来,执行文件大小有数据段,执行代码段等等,如果把这些段都合' w2 W. d7 e$ K3 r6 m% V
并起来,是不是就会把段之间的冗余有减小了呢?再试试看:添加选项:: g: T/ W2 t8 M
/merge:.data=.text /merge:.rdata=.text。再看看文件大小:1,328bytes。真的# |1 ~2 n4 \% B4 e
很不错了。
- ~' N$ [, b7 Y
- U. Y6 o+ c- B5 x* A0 n1 r6、刚才的设定确实不错,似乎达到了我们想要的极限了。但是回头想一下,如果6 x; g9 l, j/ c1 K2 @6 F: D  l
没有CRT库的话,会不会更小了?实际上确实这样。添加连接选项: /entry:' k& F( o- O; ?& W7 Y8 C0 |$ y. y) Q
main,把入口地址直接指向我们的main函数看看。得到592Bytes。
- X  P  e1 p* p: P. l( x* y5 |" w$ i# g
最终我们得到我们最后的大小592Bytes了。我想这也许是我们通过编译器能够编译! E2 G/ J- }+ p) a: b
出来的最小的代码了。
- j2 ~9 h3 C6 U8 ~9 h
) G6 l, S/ J  V! i$ F* L, g: L结论:; P5 i$ f$ f- I4 }, Z" T$ ?) c
通过上述的步骤,我们了解了如何修改那些编译连接选项来达到执行文件瘦身的目' x1 q- @1 V% u, s6 F- X& m7 l
的。但是,通常来讲,在我们的Release文件当中,并不需要如此小的执行文件。
) P% n5 {' C; D. p& r如果想达到瘦身的目的,修改为library:MutiThreaded Dll和添加/opt:nowin98已
. ?6 I  j& b$ f# z, _# l+ _7 ^" |经是很好的选择了。其他别的选项在编译的时候或多或少的有警告出现,而且,带) B8 T# O3 n# g) j# F( z5 H
有那些编译选项编出来的执行文件也不一定在各个平台上能够适用。
. f% {2 A* k" {  V5 U* ~
) w, X1 P% d$ |& N/ z1 v" w另外:如果你的执行文件即使通过了这些设定还是比较大的话,也可以通过一些7 v) o, E2 b5 y2 l8 i9 x4 S5 I7 a
EXE文件压缩工具来进行压缩。比如UPX等等。在此不再细说了。
! N5 h) f- z2 [
8 G* T1 m  {5 w8 f4 w( G9 t以上部分的不足之处,还请多多指正。
发表于 2006-10-3 13:00:07 | 显示全部楼层
谢谢楼主
回复

使用道具 举报

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

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-8-21 03:40 , Processed in 0.013618 second(s), 4 queries , Redis On.

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

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