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

瘦身你的执行文件

[复制链接]
发表于 2006-9-28 21:36:19 | 显示全部楼层 |阅读模式
在网上,有好多绿色软件,不仅功能强大,而且软件本身的体积非常小。有的通常! z' P+ C* x% j
只在几十K左右。那他们是怎么做到把软件做的怎么小的呢?现在我手把手的告诉
! N5 C. ]. k7 C' M6 J3 x( W你如何通过修改程序的编译选项来瘦身你的执行文件
* N. |9 c. a9 p8 P' g先看一个最典型的程序:
5 Y  X1 s  K# z- R#include<stdio.h>: f; N2 |# [8 v# U) ~
int main()
' X# `6 v, S- S# p, I* E4 r0 l{7 P; e  g% I6 B; J" n
printf("Hello,World");  ?" f+ c2 E  V% d; o
return 0;1 I, `3 W/ f0 g* T  c
}  x) s' F6 r4 i* B$ H  W' L5 j
* M& x% B. H3 K8 k- l, X
上面的程序之所以被称之为典型,是因为他有如下的内容:
5 V( Q3 T! X, I& c* z( y5 @1、系统函数调用:printf/ H) Y2 z. A; @  J2 v0 b. [' z; A4 m
2、有静态数据段
% p' Z4 s' N" e, x6 `( t9 |. b( ^% I5 O  I" M* a+ K
好,现在把此文件放到VisualStudio6.0中进行编译,看看文件有多大。
6 @! c5 y( R2 ~9 N  B1、用VisualStudio6.0打开HelloWorld.cpp文件,直接按F7。然后点击OK,生成3 {( u6 X6 g6 F1 m
Project文件,然后进行编译。编译完成了以后,看看Debug目录下的执行文件的大
6 Q# a" t/ _8 R0 S小,为172,096Bytes。" K9 g2 o4 h; M) ?" @: B' {
, U% E: @% K: t& x7 L* T  D' C
2、刚才编译的Debug文件,现在修改成Release文件看看。选择Win32 Release,再! C3 B) ?( S# C  u
编译。察看执行文件大小,现在成了40,960Bytes。看来Debug版本的要比Release
8 O  ]8 u3 a0 U+ K的小。/ i. ~( ]8 N1 j7 W

9 ?+ u" |$ C  X# f3、检查代码优化:发现执行文件的优化是Maximize Speed。那么修改成Minimize
1 v5 b5 d! d+ ?5 S- r+ h# m5 ASize看看。重新编译,得到执行文件的大小为:40,960Bytes。看来大小没什么变$ |7 U7 w' E6 d+ q: |' q
化。其实这是由于我们的代码本身太小的缘故,导致即使变化了也看不出来。
' G  G/ A3 |8 A% e6 p) o' I
0 @& t3 ^: ?& `7 u9 |$ H4、想想我们程序的main函数是由CRT类库进行引导的。在我们现在的设定当中,由/ i+ D. H  T* }
于采取的是系统缺省的编译连接方式(缺省为编译为Single Thread,Static! u& p- p6 p0 W* e3 Y: H! L
Library),所以,在我们的执行文件当中,包含了CRT的二进制代码。好,修改编5 V6 \8 ]3 n4 T2 ^4 \
译选项:C/C++ => Category:Code Generation => Use run-time
$ r. r* p: G1 |library:MutiThreaded Dll。编译看看:执行文件大小变成了16,384Bytes。
' i# ^+ p5 W8 a( _
1 p, u9 l# |9 w0 W8 p, Q. S5 _5、刚才的设定确实不错,一下子把执行文件大小减小到了16K。现在用UltraEdit
$ x: O' B6 [  @' g看看执行文件都是些什么内容。结果大吃一惊:基本上都是0。看来这个有减小的
2 ?0 ~7 m! J- `6 M" O7 n- F4 N! F' ^# G必要了。都知道,执行文件都有自己的代码段,数据段等等,每个段的大小也是采$ `$ W, E# c' p" W* {
用编译器缺省设定的。好,我们来修改一下段的大小看看:
) o9 O5 I: m: w  B$ C& ], W5.1 连接选项中有一个是/opt:nowin98,意思是将段的大小设定成为Win2000适应
/ n6 j! U+ s' o1 v; t2 E; Z的。编译看看:哇塞,变成了2,560byte。看来这个选项确实把文件变小了N多。# j; p1 M; K$ q4 f! _1 W' Z  [
5.2 在查察连接选项中还有没有什么特别的。发现/align:xx还可以将段大小缩9 r9 t, Z! n# P
小。通过UltraEdit察看刚才/opt:nowin98编译出来的文件,发现每个段的大小都9 f5 c. P6 q. ]. Q, U( ^
是4K的整数倍。看来/align:xx还有减小的趋势。试一把再说:添加连接选项:8 A, ]# v  D/ O9 H" y* H
/align:16(这个大小已经是能够设定的最小的了)。看看结果:1,408Bytes。厉
) B3 p  ^) K2 g) `  Q1 ?# B7 h3 u害,现在代码更小了。
6 ]5 \( y, e3 {& x5.3 现在回想起来,执行文件大小有数据段,执行代码段等等,如果把这些段都合& p3 V6 g  E0 ?' k& N8 @
并起来,是不是就会把段之间的冗余有减小了呢?再试试看:添加选项:
% J; A& O( B# C* J$ G1 j/merge:.data=.text /merge:.rdata=.text。再看看文件大小:1,328bytes。真的9 F3 u* h) E6 n) ~9 Y/ Z3 ^  C
很不错了。* a# |$ j5 ?; b4 ~4 a

- r1 o2 u+ o3 E1 f" \5 }# W; l6、刚才的设定确实不错,似乎达到了我们想要的极限了。但是回头想一下,如果: X( `" ]2 U( t3 J4 c9 \
没有CRT库的话,会不会更小了?实际上确实这样。添加连接选项: /entry:: }) ]  h. p4 C, Z
main,把入口地址直接指向我们的main函数看看。得到592Bytes。7 a6 H9 h; [1 J: W* T9 [9 U8 q
7 ~! Y9 @2 M1 {9 L' @
最终我们得到我们最后的大小592Bytes了。我想这也许是我们通过编译器能够编译% U* b1 N9 @1 ^0 J: A& z
出来的最小的代码了。
2 a* Q  Q7 Z) s( V7 I; M0 e) H, ?9 `' |3 ]
结论:
* }) D$ c7 H9 n/ J$ n+ }2 ^通过上述的步骤,我们了解了如何修改那些编译连接选项来达到执行文件瘦身的目
4 O8 c6 p+ z4 |& L% Q# g的。但是,通常来讲,在我们的Release文件当中,并不需要如此小的执行文件。5 Z6 e2 n! L3 }% b% Y
如果想达到瘦身的目的,修改为library:MutiThreaded Dll和添加/opt:nowin98已: R, `. B: I3 q7 f
经是很好的选择了。其他别的选项在编译的时候或多或少的有警告出现,而且,带
, V  ^& O) G9 w" @1 W7 E( B. _  j有那些编译选项编出来的执行文件也不一定在各个平台上能够适用。( F5 T& E8 M1 }$ v8 [  V. @

! ?' Z+ H8 e# X; @6 [另外:如果你的执行文件即使通过了这些设定还是比较大的话,也可以通过一些
) c, i  C' g& m! r6 m2 Y! WEXE文件压缩工具来进行压缩。比如UPX等等。在此不再细说了。
/ j( T0 F0 S/ B) |3 r
7 o; y+ a" f/ J, T) c# G  S以上部分的不足之处,还请多多指正。
发表于 2006-10-3 13:00:07 | 显示全部楼层
谢谢楼主
回复

使用道具 举报

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

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-2-28 02:36 , Processed in 0.058925 second(s), 5 queries , Redis On.

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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