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

瘦身你的执行文件

[复制链接]
发表于 2006-9-28 21:36:19 | 显示全部楼层 |阅读模式
在网上,有好多绿色软件,不仅功能强大,而且软件本身的体积非常小。有的通常
$ L8 |% _6 M" J只在几十K左右。那他们是怎么做到把软件做的怎么小的呢?现在我手把手的告诉8 o. ~# \' \4 _5 x/ _! G# _/ l+ a/ D* |
你如何通过修改程序的编译选项来瘦身你的执行文件) `6 u# K1 a+ @) h- O0 h
先看一个最典型的程序:
/ s% E3 ?# \/ _4 A* u#include<stdio.h>; W- R, }: m% W
int main()1 W* j+ k) ^/ }# U
{! U7 y3 b: o# p% l5 c- l
printf("Hello,World");
2 q0 \8 N- `" R' O# W0 ]' ^ return 0;
) U0 U8 Z$ Z$ G/ Z7 A# O8 n}
0 r% Y" K: d- b* A
1 w+ c  W; `) m0 T3 ^7 u0 @上面的程序之所以被称之为典型,是因为他有如下的内容:/ {$ k$ W( Y9 i! [3 f  E) ~* ]
1、系统函数调用:printf
9 L% l3 i' ~& D; F( |9 {; P2、有静态数据段: Z  a* R4 G# j5 |6 o
! m% ^; J9 y- I
好,现在把此文件放到VisualStudio6.0中进行编译,看看文件有多大。
' H/ m$ z5 X0 `$ A4 K4 h+ u4 P% U: q1、用VisualStudio6.0打开HelloWorld.cpp文件,直接按F7。然后点击OK,生成! b8 p1 |" u% O0 Z- f( u( Z
Project文件,然后进行编译。编译完成了以后,看看Debug目录下的执行文件的大$ ]& g% ]9 R$ P. w3 O6 A; N% k
小,为172,096Bytes。
* H; L/ \4 Q% b, I+ I7 E3 P1 Z- u3 I7 m, K1 T* w& {8 d
2、刚才编译的Debug文件,现在修改成Release文件看看。选择Win32 Release,再0 l% S& J+ V1 a, ]# }. S% K* W
编译。察看执行文件大小,现在成了40,960Bytes。看来Debug版本的要比Release- r) H1 \8 M( f; s. M
的小。2 s  \6 F; t/ @3 \6 _- V$ i
1 }$ V. m1 f( |# J/ e
3、检查代码优化:发现执行文件的优化是Maximize Speed。那么修改成Minimize' u3 b# e& t7 Q. s7 ]
Size看看。重新编译,得到执行文件的大小为:40,960Bytes。看来大小没什么变
2 y2 x  K3 O' @& P) G0 F. P7 ?化。其实这是由于我们的代码本身太小的缘故,导致即使变化了也看不出来。* v; X" X  l! _# O/ Y+ t+ r
; H& k) [6 I# @
4、想想我们程序的main函数是由CRT类库进行引导的。在我们现在的设定当中,由
' O: L" F8 d9 r8 @于采取的是系统缺省的编译连接方式(缺省为编译为Single Thread,Static( g) L4 v; n3 J% h) |  N
Library),所以,在我们的执行文件当中,包含了CRT的二进制代码。好,修改编" ]" d9 ~# |* l% A7 ]
译选项:C/C++ => Category:Code Generation => Use run-time
8 L& F, q2 v; V3 y! R- l3 m5 m+ W" D: llibrary:MutiThreaded Dll。编译看看:执行文件大小变成了16,384Bytes。0 p; ?: x% g5 k" ]* @" s

: D/ w- Q% E' J) N$ ]5 H5、刚才的设定确实不错,一下子把执行文件大小减小到了16K。现在用UltraEdit5 m" F( Y% ]( {1 D2 L; G
看看执行文件都是些什么内容。结果大吃一惊:基本上都是0。看来这个有减小的
5 p7 N2 p! A3 L' _( M' r* i: X必要了。都知道,执行文件都有自己的代码段,数据段等等,每个段的大小也是采
" l# R( N- r9 ]0 ]  e- w, q用编译器缺省设定的。好,我们来修改一下段的大小看看:0 ]- @8 Z0 N' h: {: o" x0 T* H
5.1 连接选项中有一个是/opt:nowin98,意思是将段的大小设定成为Win2000适应
% K, l, G/ b- o! A# U的。编译看看:哇塞,变成了2,560byte。看来这个选项确实把文件变小了N多。6 X& V# b+ c9 \, v
5.2 在查察连接选项中还有没有什么特别的。发现/align:xx还可以将段大小缩
  r0 f! A8 k9 ^! p  @$ ~  K' S小。通过UltraEdit察看刚才/opt:nowin98编译出来的文件,发现每个段的大小都! H0 N& {3 F: f; J9 g1 N; S; U
是4K的整数倍。看来/align:xx还有减小的趋势。试一把再说:添加连接选项:
" V+ C' u8 H: Z; I/align:16(这个大小已经是能够设定的最小的了)。看看结果:1,408Bytes。厉
2 t) Y$ S4 d( C. R3 o2 p" P& A害,现在代码更小了。
: L' P: C, t( I; N5.3 现在回想起来,执行文件大小有数据段,执行代码段等等,如果把这些段都合, e& C& k6 q* V* F, M5 H& p
并起来,是不是就会把段之间的冗余有减小了呢?再试试看:添加选项:
! Y( r8 H$ Q. Y/merge:.data=.text /merge:.rdata=.text。再看看文件大小:1,328bytes。真的- ?& B) K* ?9 b
很不错了。4 b; t% P) H8 X" p% `

- {1 P" k7 K' A" f' e: q6、刚才的设定确实不错,似乎达到了我们想要的极限了。但是回头想一下,如果2 O. i; c' }/ W0 @( `* n3 f- _
没有CRT库的话,会不会更小了?实际上确实这样。添加连接选项: /entry:2 J7 B5 h' L2 V5 l- ?
main,把入口地址直接指向我们的main函数看看。得到592Bytes。4 _: w0 ~0 |6 d3 C7 A  j

, S5 h0 ~9 z& h0 m. m最终我们得到我们最后的大小592Bytes了。我想这也许是我们通过编译器能够编译2 ?' M- ~- w4 x) p/ e) L
出来的最小的代码了。
4 t8 O3 h4 p/ o/ _& e2 ?( C: H* f5 O& M0 O
结论:
3 l# w5 C7 _" c通过上述的步骤,我们了解了如何修改那些编译连接选项来达到执行文件瘦身的目, Y( y! S) x( a) g( r$ z
的。但是,通常来讲,在我们的Release文件当中,并不需要如此小的执行文件。3 {" w7 Y, N4 S# m
如果想达到瘦身的目的,修改为library:MutiThreaded Dll和添加/opt:nowin98已
* S  w& E+ @8 \6 j: x3 Q. ~6 f经是很好的选择了。其他别的选项在编译的时候或多或少的有警告出现,而且,带; v/ }) w1 d9 s/ {1 `
有那些编译选项编出来的执行文件也不一定在各个平台上能够适用。
5 Y9 A; f) ^0 u; @; J
1 W' `+ |" R  Z7 s0 M$ o另外:如果你的执行文件即使通过了这些设定还是比较大的话,也可以通过一些1 v- q3 k+ a2 D$ A! E+ H
EXE文件压缩工具来进行压缩。比如UPX等等。在此不再细说了。
' Z( m; h1 G* p" ~7 i
+ @, L8 N' x1 R/ o, Z以上部分的不足之处,还请多多指正。
发表于 2006-10-3 13:00:07 | 显示全部楼层
谢谢楼主
回复

使用道具 举报

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

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-5-10 14:10 , Processed in 0.065436 second(s), 6 queries , Redis On.

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

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