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

瘦身你的执行文件

[复制链接]
发表于 2006-9-28 21:36:19 | 显示全部楼层 |阅读模式
在网上,有好多绿色软件,不仅功能强大,而且软件本身的体积非常小。有的通常
, O: `4 h: R9 z8 r只在几十K左右。那他们是怎么做到把软件做的怎么小的呢?现在我手把手的告诉
6 c3 Y6 z' s& ~  f% G你如何通过修改程序的编译选项来瘦身你的执行文件3 N% @1 ?1 k8 I
先看一个最典型的程序:
# j5 D. Y/ ?6 M& \" p4 d1 h& B#include<stdio.h>
( ~1 h9 J) N7 }3 x5 Xint main()4 N: p) G9 o% V) P, A; o& x0 |/ X& t
{
# K+ f0 t9 {+ P5 ~+ L printf("Hello,World");
5 ^5 G1 f$ C1 w, B# I3 O* Q: w% z return 0;
! S$ _& p# _' l, z; o$ N4 q. ^}
( L( J( R3 b( P0 |* w1 R* R1 B. v# c+ V4 [
上面的程序之所以被称之为典型,是因为他有如下的内容:0 ?! p- Z! O- p4 u" _" `
1、系统函数调用:printf  X8 C0 u$ D/ d: P( c+ i; G: n
2、有静态数据段
( \. Z+ K9 `2 w. }( i
; O  S  S% u6 ]& a5 }; |- K好,现在把此文件放到VisualStudio6.0中进行编译,看看文件有多大。- f& @! R# Y$ L+ I$ s
1、用VisualStudio6.0打开HelloWorld.cpp文件,直接按F7。然后点击OK,生成
, I" J0 |/ b& h' {3 X5 _8 CProject文件,然后进行编译。编译完成了以后,看看Debug目录下的执行文件的大
) @4 g: X7 v; @0 R3 n0 L0 S小,为172,096Bytes。
+ N8 ]' C" E, \9 b2 m2 J3 [
% d: U, s: ~7 ]; Z* s; {2、刚才编译的Debug文件,现在修改成Release文件看看。选择Win32 Release,再0 J4 g# {. v, ?# q# l% d
编译。察看执行文件大小,现在成了40,960Bytes。看来Debug版本的要比Release
" j! ^0 q2 c% i# T" t; j1 ]7 }的小。, G! X# c2 b; o5 O( ~

/ r5 V9 G1 W& y9 d- ]3、检查代码优化:发现执行文件的优化是Maximize Speed。那么修改成Minimize
/ I3 Q4 X/ Z& u3 `" LSize看看。重新编译,得到执行文件的大小为:40,960Bytes。看来大小没什么变
% p2 {  N3 t5 _: U1 B' Z9 p化。其实这是由于我们的代码本身太小的缘故,导致即使变化了也看不出来。6 ?' q- g2 [$ @4 I$ `, T

* m7 V! i, w8 N/ O2 y! j3 B, ]4、想想我们程序的main函数是由CRT类库进行引导的。在我们现在的设定当中,由; L  ?- z& U5 {. ]+ p
于采取的是系统缺省的编译连接方式(缺省为编译为Single Thread,Static9 R2 ~% g8 D( q5 p  y2 s
Library),所以,在我们的执行文件当中,包含了CRT的二进制代码。好,修改编
7 L) t( o5 I8 r+ C( V译选项:C/C++ => Category:Code Generation => Use run-time4 {" y7 f, [& E
library:MutiThreaded Dll。编译看看:执行文件大小变成了16,384Bytes。* }. N/ p3 y6 C' ]

3 c! q. W" J3 T1 g5、刚才的设定确实不错,一下子把执行文件大小减小到了16K。现在用UltraEdit
9 f) V$ Y8 F1 r4 t, N9 S1 h! q看看执行文件都是些什么内容。结果大吃一惊:基本上都是0。看来这个有减小的" M% c3 ^/ b. e; i( [4 G# G% @
必要了。都知道,执行文件都有自己的代码段,数据段等等,每个段的大小也是采
5 ]! Y  Z$ S) |) M  ~$ A用编译器缺省设定的。好,我们来修改一下段的大小看看:
& \( M% k, ~1 \1 |5.1 连接选项中有一个是/opt:nowin98,意思是将段的大小设定成为Win2000适应
& `. t9 ^4 s3 i的。编译看看:哇塞,变成了2,560byte。看来这个选项确实把文件变小了N多。
/ D+ j$ o& v5 E* i6 a% }5.2 在查察连接选项中还有没有什么特别的。发现/align:xx还可以将段大小缩
/ Y) Q' [& ?( ]: H小。通过UltraEdit察看刚才/opt:nowin98编译出来的文件,发现每个段的大小都
/ w' P% }3 C" R6 |. \0 Y1 \# C是4K的整数倍。看来/align:xx还有减小的趋势。试一把再说:添加连接选项:
$ E. \1 p6 Q2 c* |  M# [* J* y% L/align:16(这个大小已经是能够设定的最小的了)。看看结果:1,408Bytes。厉
3 N  W# K- B' j; a, o$ R8 w害,现在代码更小了。
( ^3 k3 O9 h& J8 H5.3 现在回想起来,执行文件大小有数据段,执行代码段等等,如果把这些段都合6 s* m/ Y# @; [6 o, c9 B
并起来,是不是就会把段之间的冗余有减小了呢?再试试看:添加选项:
* O0 {. m2 `* |/ C2 n6 K8 @3 O! F/merge:.data=.text /merge:.rdata=.text。再看看文件大小:1,328bytes。真的
+ c1 W! U4 M, x8 j很不错了。
. @% N0 c9 T" F+ s/ S
) x3 m7 ?& F3 B& o6、刚才的设定确实不错,似乎达到了我们想要的极限了。但是回头想一下,如果
9 v6 \; A% z7 u6 z/ [, C没有CRT库的话,会不会更小了?实际上确实这样。添加连接选项: /entry:
+ j! s1 Y- |4 Tmain,把入口地址直接指向我们的main函数看看。得到592Bytes。% Q7 \8 W& A/ t3 d
; a% ~  {: p+ E. ?1 p
最终我们得到我们最后的大小592Bytes了。我想这也许是我们通过编译器能够编译
; H/ a. ~$ b' I( N! t出来的最小的代码了。+ o& X6 _2 e7 H9 p- N7 R* Z2 u

) z5 r0 i, q5 S, q% _0 V& F2 @结论:
) q5 [2 I+ {" ^通过上述的步骤,我们了解了如何修改那些编译连接选项来达到执行文件瘦身的目
4 |* C' l/ Z# }  d的。但是,通常来讲,在我们的Release文件当中,并不需要如此小的执行文件。9 H# F; ]  |' V0 a
如果想达到瘦身的目的,修改为library:MutiThreaded Dll和添加/opt:nowin98已; E" G0 F$ ]" a: d
经是很好的选择了。其他别的选项在编译的时候或多或少的有警告出现,而且,带
4 b0 Y/ p* _' R# C8 {有那些编译选项编出来的执行文件也不一定在各个平台上能够适用。$ x* ^8 k! |4 p7 {7 |  D
& A5 a% u* e- D' p0 d7 t8 W8 j
另外:如果你的执行文件即使通过了这些设定还是比较大的话,也可以通过一些0 e/ E" J# N1 G
EXE文件压缩工具来进行压缩。比如UPX等等。在此不再细说了。
3 O% {4 s2 w% U5 V' q3 M2 j
0 f: N3 i4 `% r# U以上部分的不足之处,还请多多指正。
发表于 2006-10-3 13:00:07 | 显示全部楼层
谢谢楼主
回复

使用道具 举报

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

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-8-28 06:52 , Processed in 0.015013 second(s), 5 queries , Redis On.

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

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