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

瘦身你的执行文件

[复制链接]
发表于 2006-9-28 21:36:19 | 显示全部楼层 |阅读模式
在网上,有好多绿色软件,不仅功能强大,而且软件本身的体积非常小。有的通常
$ S" ?6 y+ B: U, ?只在几十K左右。那他们是怎么做到把软件做的怎么小的呢?现在我手把手的告诉% W0 D" g) @  e. n' r' V; e  u( E
你如何通过修改程序的编译选项来瘦身你的执行文件
6 a0 z9 Y- o3 N) X$ s! `先看一个最典型的程序:
3 y; B- a- H4 J% u5 d( ?#include<stdio.h>( [; @( K' H: w. d
int main()
6 j: b  `6 W. v& t) p1 h{3 J; I2 g! T7 a: \# c" Z+ _
printf("Hello,World");
6 H  L4 W5 S! y9 a! S/ d! l, C return 0;; B/ ]& i- d* u. C. i' D
}
1 q: J% k3 v% {
: {  v. }+ i9 B! I' j# w% W上面的程序之所以被称之为典型,是因为他有如下的内容:
6 ?, M- |* e/ q8 l. q1 g1、系统函数调用:printf" \! q% {6 l( y! H3 I
2、有静态数据段
6 Y& M9 E+ ^8 \2 O! M6 M7 e9 f# @/ I9 B1 O8 i+ a: H6 D9 V* O" F
好,现在把此文件放到VisualStudio6.0中进行编译,看看文件有多大。
+ O0 I" c  g4 Y1 O' ~. z) _1 Z; s1、用VisualStudio6.0打开HelloWorld.cpp文件,直接按F7。然后点击OK,生成% A( u# h, y; L$ a4 s
Project文件,然后进行编译。编译完成了以后,看看Debug目录下的执行文件的大2 b3 ^! N; G1 E  t  Q+ U; v
小,为172,096Bytes。
7 U$ k  d9 O$ t: Y$ ~7 f/ t, j8 d+ p) J3 U2 U7 i0 L! ~
2、刚才编译的Debug文件,现在修改成Release文件看看。选择Win32 Release,再) a0 T; _* ?# h/ V) G
编译。察看执行文件大小,现在成了40,960Bytes。看来Debug版本的要比Release
& s; Y2 `3 W) q3 p% @' k的小。
3 ?5 u3 N# \) Y! u+ C
: H6 p# G! A6 O' `3、检查代码优化:发现执行文件的优化是Maximize Speed。那么修改成Minimize
9 j- [& i* {2 E8 ^" g8 ^1 \Size看看。重新编译,得到执行文件的大小为:40,960Bytes。看来大小没什么变
3 H! u% m5 U" {2 u1 ^6 \* T化。其实这是由于我们的代码本身太小的缘故,导致即使变化了也看不出来。
/ x2 T+ [1 t* z# j  F4 [4 p! V+ b& B; v: B* p3 A9 t
4、想想我们程序的main函数是由CRT类库进行引导的。在我们现在的设定当中,由
  Q- T0 v% p# V$ G) y于采取的是系统缺省的编译连接方式(缺省为编译为Single Thread,Static
2 v+ y$ r+ \! C0 R. o1 F6 S3 b% o1 NLibrary),所以,在我们的执行文件当中,包含了CRT的二进制代码。好,修改编
: F3 f- P$ h0 g! `. y& b. H译选项:C/C++ => Category:Code Generation => Use run-time
9 J$ }$ Z. g- G; ]& I- ylibrary:MutiThreaded Dll。编译看看:执行文件大小变成了16,384Bytes。
* M# u( ]3 n* z, G4 V1 x; H0 O  \3 ~# q$ U! m. a
5、刚才的设定确实不错,一下子把执行文件大小减小到了16K。现在用UltraEdit$ I, {' o+ g# g& n0 I/ v3 S! E: C
看看执行文件都是些什么内容。结果大吃一惊:基本上都是0。看来这个有减小的
4 b/ r$ U# \, c! P$ t( i# A必要了。都知道,执行文件都有自己的代码段,数据段等等,每个段的大小也是采
- {7 m. c! F' \/ z7 m5 x( A' ?用编译器缺省设定的。好,我们来修改一下段的大小看看:
1 C2 T) f; Y" V& Q9 Z4 L5.1 连接选项中有一个是/opt:nowin98,意思是将段的大小设定成为Win2000适应
  J, X* a/ u1 g) a( X1 F的。编译看看:哇塞,变成了2,560byte。看来这个选项确实把文件变小了N多。
9 |  S+ `; n5 b; M# T  j# w5.2 在查察连接选项中还有没有什么特别的。发现/align:xx还可以将段大小缩( F7 X* f& {1 A! P0 P
小。通过UltraEdit察看刚才/opt:nowin98编译出来的文件,发现每个段的大小都
* a# k5 p( C2 _( D是4K的整数倍。看来/align:xx还有减小的趋势。试一把再说:添加连接选项:
6 P7 S* r8 S8 K; {% b  ^8 X$ [/align:16(这个大小已经是能够设定的最小的了)。看看结果:1,408Bytes。厉
/ G% o  v! V4 b3 w- d9 a害,现在代码更小了。0 Z+ p3 Z' C4 v& y0 E( g- ~
5.3 现在回想起来,执行文件大小有数据段,执行代码段等等,如果把这些段都合, S4 Q2 c( n: ~* R3 `0 o# r9 B
并起来,是不是就会把段之间的冗余有减小了呢?再试试看:添加选项:$ E/ O# j* N; U' `. W
/merge:.data=.text /merge:.rdata=.text。再看看文件大小:1,328bytes。真的
: b7 ~/ d8 ]/ j4 W/ D" Z很不错了。- H( A# s% W9 }2 ]1 s

. s$ Y9 I) C3 u8 k& E& ~0 ?1 v6、刚才的设定确实不错,似乎达到了我们想要的极限了。但是回头想一下,如果6 R1 m; h! r$ L" _+ j
没有CRT库的话,会不会更小了?实际上确实这样。添加连接选项: /entry:
; I) A, R5 ]( |& L% tmain,把入口地址直接指向我们的main函数看看。得到592Bytes。
- Z' d6 v8 G  y! v) e7 `/ U. x
7 [8 [' t" y& O) P最终我们得到我们最后的大小592Bytes了。我想这也许是我们通过编译器能够编译& ]/ G7 i) s) s% A
出来的最小的代码了。
& k0 {9 C. h+ ^% |/ o& i
& a, C9 O3 w" X0 T& g结论:# J2 I8 e: q5 @  V/ u
通过上述的步骤,我们了解了如何修改那些编译连接选项来达到执行文件瘦身的目( Q' _: X( V4 J6 k% D3 N7 X
的。但是,通常来讲,在我们的Release文件当中,并不需要如此小的执行文件。$ P7 C  d/ q+ J$ c' u  ?+ ?" b
如果想达到瘦身的目的,修改为library:MutiThreaded Dll和添加/opt:nowin98已
2 M* d0 ]( w1 `1 N经是很好的选择了。其他别的选项在编译的时候或多或少的有警告出现,而且,带# o' T% E; h  A( y
有那些编译选项编出来的执行文件也不一定在各个平台上能够适用。3 a7 c: k9 B5 V; v

% ^( X4 A* p4 `" [2 {: F另外:如果你的执行文件即使通过了这些设定还是比较大的话,也可以通过一些. p3 B( I! u1 u1 W9 p3 u4 z* Z5 i
EXE文件压缩工具来进行压缩。比如UPX等等。在此不再细说了。
! g$ v' V; q! c7 _  A
9 ^3 d& d1 d5 l$ q0 }- f' z1 V以上部分的不足之处,还请多多指正。
发表于 2006-10-3 13:00:07 | 显示全部楼层
谢谢楼主
回复

使用道具 举报

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

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-9-10 16:24 , Processed in 0.016201 second(s), 5 queries , Redis On.

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

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