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

瘦身你的执行文件

[复制链接]
发表于 2006-9-28 21:36:19 | 显示全部楼层 |阅读模式
在网上,有好多绿色软件,不仅功能强大,而且软件本身的体积非常小。有的通常
' K; v. r  _8 I7 _$ v" `* V只在几十K左右。那他们是怎么做到把软件做的怎么小的呢?现在我手把手的告诉
4 W4 a/ }2 b$ H! e1 B你如何通过修改程序的编译选项来瘦身你的执行文件9 m0 h* e2 P3 \$ n/ g9 H6 k, `8 N8 Z
先看一个最典型的程序:
8 H4 t# l; y$ x#include<stdio.h>
5 q  s% y- C% Z# ?  G, pint main(): @  D0 @( T( A3 U8 m: F
{
( V# h0 M: h# [ printf("Hello,World");
- m3 h0 }  `$ @/ U7 _ return 0;
; r, f# b$ ?2 J* a0 R" O3 t}2 |! [+ I6 b2 i) _" c5 ?9 \3 l, V
. ^& t* t9 G7 S9 F
上面的程序之所以被称之为典型,是因为他有如下的内容:' ]( o( ?. Z7 \& g! Y
1、系统函数调用:printf
6 T, {7 b' L9 |% d  ^( [2、有静态数据段1 B2 @) K' C5 I: Q1 a- X# {& P
# }# ]! N5 |9 s, K& Q8 J6 m% Y0 C2 X
好,现在把此文件放到VisualStudio6.0中进行编译,看看文件有多大。8 i& V2 H; z# u
1、用VisualStudio6.0打开HelloWorld.cpp文件,直接按F7。然后点击OK,生成; c% S/ v* g/ O! W6 s
Project文件,然后进行编译。编译完成了以后,看看Debug目录下的执行文件的大" {9 o- u% ]8 ?4 y
小,为172,096Bytes。0 j/ }: q* @1 l. W, H" a% w. H
# _8 w7 W+ R8 g7 X/ P
2、刚才编译的Debug文件,现在修改成Release文件看看。选择Win32 Release,再+ C0 T* j% s* s7 h3 i
编译。察看执行文件大小,现在成了40,960Bytes。看来Debug版本的要比Release
6 z& L, w& B/ F4 \: _的小。
" l" \8 c+ _% G# q/ u! e/ l. C0 R1 Z5 D4 T. L, M5 l+ U: M
3、检查代码优化:发现执行文件的优化是Maximize Speed。那么修改成Minimize7 }! |2 V2 r0 x# E
Size看看。重新编译,得到执行文件的大小为:40,960Bytes。看来大小没什么变' |$ r! W: \! g' G0 X8 V9 y) t8 o
化。其实这是由于我们的代码本身太小的缘故,导致即使变化了也看不出来。
" D- O* D" n1 M9 a  v
# {& H7 b# E2 |4、想想我们程序的main函数是由CRT类库进行引导的。在我们现在的设定当中,由* q& ~- g% w, o/ M
于采取的是系统缺省的编译连接方式(缺省为编译为Single Thread,Static! u" c7 M. O. `4 a  a
Library),所以,在我们的执行文件当中,包含了CRT的二进制代码。好,修改编
8 {5 W2 P# D6 ?: m8 A译选项:C/C++ => Category:Code Generation => Use run-time
% v3 t1 M" D* u3 H8 Olibrary:MutiThreaded Dll。编译看看:执行文件大小变成了16,384Bytes。# `1 q' F# b9 a/ U
& P7 J+ o3 A9 V, e
5、刚才的设定确实不错,一下子把执行文件大小减小到了16K。现在用UltraEdit
1 G2 j3 N0 l6 X! {! b$ z看看执行文件都是些什么内容。结果大吃一惊:基本上都是0。看来这个有减小的
1 S7 K$ s  ]  e( i  w必要了。都知道,执行文件都有自己的代码段,数据段等等,每个段的大小也是采
/ L* A- q: ]6 R2 a用编译器缺省设定的。好,我们来修改一下段的大小看看:3 s( q" V- `( A3 Y
5.1 连接选项中有一个是/opt:nowin98,意思是将段的大小设定成为Win2000适应0 u5 r$ C- U' q& s+ p
的。编译看看:哇塞,变成了2,560byte。看来这个选项确实把文件变小了N多。8 m* R4 W# r" a! y$ U
5.2 在查察连接选项中还有没有什么特别的。发现/align:xx还可以将段大小缩; Z! e. p+ N; }2 _6 j
小。通过UltraEdit察看刚才/opt:nowin98编译出来的文件,发现每个段的大小都8 N6 X4 |) }8 _3 J6 o) Z- B- U
是4K的整数倍。看来/align:xx还有减小的趋势。试一把再说:添加连接选项:
" B0 Z3 g. \; R& A1 a% I/align:16(这个大小已经是能够设定的最小的了)。看看结果:1,408Bytes。厉3 U* _2 f5 M8 i3 m6 B6 W' V6 |2 `
害,现在代码更小了。" C- S5 ~0 \) P4 o) e" \! \& i
5.3 现在回想起来,执行文件大小有数据段,执行代码段等等,如果把这些段都合9 s7 T0 J3 r  S# {' j+ k# F
并起来,是不是就会把段之间的冗余有减小了呢?再试试看:添加选项:6 e# H3 J2 m  ~7 ~: S- x, l
/merge:.data=.text /merge:.rdata=.text。再看看文件大小:1,328bytes。真的8 C  T1 T! v' k+ Q- v
很不错了。
% f  w4 i5 \* G, v7 e
! B! n+ b( y1 B6 P$ w2 Q6、刚才的设定确实不错,似乎达到了我们想要的极限了。但是回头想一下,如果9 @" ?9 I, C7 b$ K$ F& u
没有CRT库的话,会不会更小了?实际上确实这样。添加连接选项: /entry:
: @' t  U7 L8 ^% A6 _* {. @1 I* x% qmain,把入口地址直接指向我们的main函数看看。得到592Bytes。
; y" Y) I/ T* Y4 |' \2 N# N" \7 S
' F! @! \' m  f6 w( I最终我们得到我们最后的大小592Bytes了。我想这也许是我们通过编译器能够编译
. X$ n  F' O) D, ]1 S出来的最小的代码了。* T; l( o( X: F2 x9 ]+ y4 _

; h2 e3 Z! {) v% S0 O: J结论:0 ^4 }4 _: W- m
通过上述的步骤,我们了解了如何修改那些编译连接选项来达到执行文件瘦身的目! r0 s  [8 S9 {- t9 e
的。但是,通常来讲,在我们的Release文件当中,并不需要如此小的执行文件。
/ h% Z- D* |' ^1 q, Q& F1 E* T如果想达到瘦身的目的,修改为library:MutiThreaded Dll和添加/opt:nowin98已
3 D9 h7 p& {* M% b6 r0 ~0 I经是很好的选择了。其他别的选项在编译的时候或多或少的有警告出现,而且,带3 W' I/ R9 m' `# t  ]. Z5 p# f
有那些编译选项编出来的执行文件也不一定在各个平台上能够适用。5 L) r3 `/ K' y2 E5 R* i  q' h
$ s9 P' U  w  Z- f4 j
另外:如果你的执行文件即使通过了这些设定还是比较大的话,也可以通过一些( b+ Q4 Q7 N& O; }% r/ r. K8 Y3 k
EXE文件压缩工具来进行压缩。比如UPX等等。在此不再细说了。
! d$ r8 [$ P. l% ^$ |$ `# {- i& Q7 x. \! @1 E* m8 O4 ]. g
以上部分的不足之处,还请多多指正。
发表于 2006-10-3 13:00:07 | 显示全部楼层
谢谢楼主
回复

使用道具 举报

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

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-9-11 17:46 , Processed in 0.013568 second(s), 4 queries , Redis On.

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

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