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

瘦身你的执行文件

[复制链接]
发表于 2006-9-28 21:36:19 | 显示全部楼层 |阅读模式
在网上,有好多绿色软件,不仅功能强大,而且软件本身的体积非常小。有的通常2 ^. ^3 Q% X( w# o3 j
只在几十K左右。那他们是怎么做到把软件做的怎么小的呢?现在我手把手的告诉5 N2 _6 r5 |4 O- l, j5 X2 \
你如何通过修改程序的编译选项来瘦身你的执行文件4 B4 M/ T# n  A4 K3 M9 ]
先看一个最典型的程序: 9 C8 B* ?) f2 W; J4 X
#include<stdio.h>
9 H4 {+ o! W0 Iint main()
0 D9 w1 C( w1 P- p{' q: m* |8 }4 ^* t' T! W0 a" }
printf("Hello,World");
9 g5 Q3 D: T) l# D6 Q, c return 0;) Z  z( |" U- r; U
}
' W3 g: B. e8 R+ Q; L4 I9 F( S/ e, p2 d2 i. ~$ B7 Y/ }
上面的程序之所以被称之为典型,是因为他有如下的内容:/ J$ s) x* e- x+ t. R/ }2 H8 J
1、系统函数调用:printf
" e' g' X; P3 O! _9 c, p" T4 x, w) h2、有静态数据段
- j7 F' `$ ]: ~* y2 l7 o; p# r! z5 @- V* O: e
好,现在把此文件放到VisualStudio6.0中进行编译,看看文件有多大。
8 Z0 u5 N0 m9 i, ?* P9 h1、用VisualStudio6.0打开HelloWorld.cpp文件,直接按F7。然后点击OK,生成
1 }3 f; l; F8 k/ jProject文件,然后进行编译。编译完成了以后,看看Debug目录下的执行文件的大
; I1 X3 @" e7 T- _' y小,为172,096Bytes。
7 E- k2 v2 `2 i+ L2 R# ^9 V$ R9 `: n2 |: Y, ~
2、刚才编译的Debug文件,现在修改成Release文件看看。选择Win32 Release,再( Z6 R: l! _" G$ L; @
编译。察看执行文件大小,现在成了40,960Bytes。看来Debug版本的要比Release( a2 n2 V0 W5 B/ O4 }
的小。
& ]/ q& j& [. L, @' X1 t7 J; Q, X# p5 k% L0 W' \
3、检查代码优化:发现执行文件的优化是Maximize Speed。那么修改成Minimize
* i8 |1 W- T8 d2 p  kSize看看。重新编译,得到执行文件的大小为:40,960Bytes。看来大小没什么变
- ^/ I$ ?: K# x. G6 F. Y% d化。其实这是由于我们的代码本身太小的缘故,导致即使变化了也看不出来。7 n% X# S, @/ n( D
; f( ?3 i' M4 ]/ a5 h
4、想想我们程序的main函数是由CRT类库进行引导的。在我们现在的设定当中,由1 [- Z6 E/ x) P. I! |) D
于采取的是系统缺省的编译连接方式(缺省为编译为Single Thread,Static  A8 N: D; H" S. m! Z
Library),所以,在我们的执行文件当中,包含了CRT的二进制代码。好,修改编0 g; [( ]1 W/ T
译选项:C/C++ => Category:Code Generation => Use run-time
2 ?% y8 v- n- }5 k3 g% `# s# ~4 plibrary:MutiThreaded Dll。编译看看:执行文件大小变成了16,384Bytes。6 F  }2 Y  `0 B% d( ~/ G0 j
/ `% @, @- U& l; N
5、刚才的设定确实不错,一下子把执行文件大小减小到了16K。现在用UltraEdit$ D: p" w0 C( `1 F! v3 G
看看执行文件都是些什么内容。结果大吃一惊:基本上都是0。看来这个有减小的) l$ z5 e; r5 X' t% P) o
必要了。都知道,执行文件都有自己的代码段,数据段等等,每个段的大小也是采- \- H* H7 c9 ~2 P+ g9 y
用编译器缺省设定的。好,我们来修改一下段的大小看看:* j8 R/ f  X0 F8 ^3 z
5.1 连接选项中有一个是/opt:nowin98,意思是将段的大小设定成为Win2000适应* r/ ^% M- _" G8 B- X  ~
的。编译看看:哇塞,变成了2,560byte。看来这个选项确实把文件变小了N多。
# q- W0 R0 b( T6 w) }5.2 在查察连接选项中还有没有什么特别的。发现/align:xx还可以将段大小缩
0 A4 J4 W; w: Q- d* u; P小。通过UltraEdit察看刚才/opt:nowin98编译出来的文件,发现每个段的大小都6 M- V, Q3 y$ [2 j0 ^% v) w
是4K的整数倍。看来/align:xx还有减小的趋势。试一把再说:添加连接选项:; O3 h" {2 ?& ^5 \' W6 u
/align:16(这个大小已经是能够设定的最小的了)。看看结果:1,408Bytes。厉* x6 Q6 L. M, b7 v
害,现在代码更小了。
; j2 P- l. s/ W5 o2 v7 h8 H3 b0 R9 p5.3 现在回想起来,执行文件大小有数据段,执行代码段等等,如果把这些段都合/ Y- A- q8 Z1 M2 O1 X+ b
并起来,是不是就会把段之间的冗余有减小了呢?再试试看:添加选项:( P0 e! I; _3 m  q9 m
/merge:.data=.text /merge:.rdata=.text。再看看文件大小:1,328bytes。真的
7 |6 W* D% s; _2 y很不错了。; `( I9 {$ Y0 q( c- k  c& @+ ?

% w4 m+ J5 k* R# |) D) h- }  l6、刚才的设定确实不错,似乎达到了我们想要的极限了。但是回头想一下,如果9 r! ~: a( l' V1 S# t. G8 v" f
没有CRT库的话,会不会更小了?实际上确实这样。添加连接选项: /entry:
9 ^6 }* P1 S# o+ Jmain,把入口地址直接指向我们的main函数看看。得到592Bytes。( s) Z" q9 k& m* a/ A0 n8 I" S
' m+ y- R0 ^& a
最终我们得到我们最后的大小592Bytes了。我想这也许是我们通过编译器能够编译) ?2 n# N* S9 g. a6 c/ C4 s
出来的最小的代码了。' T" L/ C, C/ G$ E) g

# K. S7 h9 c$ W+ B( |结论:
( v) C$ J0 V+ p+ A+ z. m( ~通过上述的步骤,我们了解了如何修改那些编译连接选项来达到执行文件瘦身的目2 j  f9 `8 L. q3 W; R) K
的。但是,通常来讲,在我们的Release文件当中,并不需要如此小的执行文件。2 G' i+ G. a  p7 s* A& V. X
如果想达到瘦身的目的,修改为library:MutiThreaded Dll和添加/opt:nowin98已
% B) m( ?( Z: s- t1 u经是很好的选择了。其他别的选项在编译的时候或多或少的有警告出现,而且,带& ]' i5 c' T6 r& M5 t9 n
有那些编译选项编出来的执行文件也不一定在各个平台上能够适用。
2 a5 w8 c. f- v6 Z* m6 t+ W& m( i0 r
另外:如果你的执行文件即使通过了这些设定还是比较大的话,也可以通过一些
; A, I  a+ @2 s- [- ?: qEXE文件压缩工具来进行压缩。比如UPX等等。在此不再细说了。
, H  [! l/ m) o" X! D$ ^3 y$ Y2 |) A* I0 [6 G) u) i- h
以上部分的不足之处,还请多多指正。
发表于 2006-10-3 13:00:07 | 显示全部楼层
谢谢楼主
回复

使用道具 举报

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

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-7-7 11:25 , Processed in 0.053041 second(s), 4 queries , Redis On.

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

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