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

瘦身你的执行文件

[复制链接]
发表于 2006-9-28 21:36:19 | 显示全部楼层 |阅读模式
在网上,有好多绿色软件,不仅功能强大,而且软件本身的体积非常小。有的通常
; [7 |$ F- m/ N9 }% d$ J( W- U% q只在几十K左右。那他们是怎么做到把软件做的怎么小的呢?现在我手把手的告诉
6 G& |0 M! ^+ D4 r0 @你如何通过修改程序的编译选项来瘦身你的执行文件
% T1 T( r: x* k, Z+ _+ E  E4 Z: t先看一个最典型的程序: - e& h. C0 X) r3 U0 g- i# [
#include<stdio.h>
' @+ {0 ?2 ]: F# n- aint main()
) N9 k6 Y5 P$ i" w' }. R/ F/ k{
1 r2 s* U4 o. p# r$ W' o printf("Hello,World");
% d1 ]1 _$ l: v, |4 R return 0;% x( l4 X1 {5 G, {2 |
}
$ U+ m' }/ G% O  i. M5 l4 z
0 B/ v! R" J6 Y# C) d2 \上面的程序之所以被称之为典型,是因为他有如下的内容:- `5 m+ L$ P2 S3 N1 E4 _
1、系统函数调用:printf% o; h( s  A! c
2、有静态数据段
/ |' E) ]9 G7 v- w
: F) K- P& t0 n5 [好,现在把此文件放到VisualStudio6.0中进行编译,看看文件有多大。
$ j1 ]' l: o3 }( ~1 ^: B1、用VisualStudio6.0打开HelloWorld.cpp文件,直接按F7。然后点击OK,生成4 |% @2 k! |! }: B& Y, U
Project文件,然后进行编译。编译完成了以后,看看Debug目录下的执行文件的大
, j) k! s- \7 ^8 C: _* \+ v小,为172,096Bytes。
( e3 e9 D1 O9 }* @  j: }5 g9 W2 p3 N3 \
2、刚才编译的Debug文件,现在修改成Release文件看看。选择Win32 Release,再
; J0 A* s& p  O' L( M( D2 q- ?编译。察看执行文件大小,现在成了40,960Bytes。看来Debug版本的要比Release
& J0 e8 J0 @3 O$ _  }0 ^5 L的小。
' k# s9 j) X8 k4 m/ `* c" {8 c0 P' F2 r& w" |2 j, Q
3、检查代码优化:发现执行文件的优化是Maximize Speed。那么修改成Minimize
0 v; L/ Y3 M  dSize看看。重新编译,得到执行文件的大小为:40,960Bytes。看来大小没什么变1 d5 X* \& y' `& i, z
化。其实这是由于我们的代码本身太小的缘故,导致即使变化了也看不出来。
8 [  e0 K- i; h# z% z) ?+ G# ^* j3 p! p, F* V2 f6 @
4、想想我们程序的main函数是由CRT类库进行引导的。在我们现在的设定当中,由
5 J$ {$ c! o; \2 y: i. n6 y于采取的是系统缺省的编译连接方式(缺省为编译为Single Thread,Static- a: C) C$ E* b/ \- Q; Q
Library),所以,在我们的执行文件当中,包含了CRT的二进制代码。好,修改编
( k% B' w, ?' D7 f译选项:C/C++ => Category:Code Generation => Use run-time
! b% `& \; d1 h6 vlibrary:MutiThreaded Dll。编译看看:执行文件大小变成了16,384Bytes。! A3 R/ q" r' Y$ I9 @
& [1 ~, i" T9 W. Y6 w, i0 B
5、刚才的设定确实不错,一下子把执行文件大小减小到了16K。现在用UltraEdit. ^; \% U, ~: s' X3 O
看看执行文件都是些什么内容。结果大吃一惊:基本上都是0。看来这个有减小的
3 H! [1 Y2 g. ]! T必要了。都知道,执行文件都有自己的代码段,数据段等等,每个段的大小也是采
1 z5 d7 p6 X7 G, R/ Y用编译器缺省设定的。好,我们来修改一下段的大小看看:) I+ z4 N2 d( ]1 d
5.1 连接选项中有一个是/opt:nowin98,意思是将段的大小设定成为Win2000适应+ D1 A- r  W, d/ k; r9 V
的。编译看看:哇塞,变成了2,560byte。看来这个选项确实把文件变小了N多。
8 Z$ i: J, f" Y' S3 @6 R4 X5.2 在查察连接选项中还有没有什么特别的。发现/align:xx还可以将段大小缩( L7 e* w7 }+ P  L; a, J" v! h
小。通过UltraEdit察看刚才/opt:nowin98编译出来的文件,发现每个段的大小都
. M6 s  b0 s  f是4K的整数倍。看来/align:xx还有减小的趋势。试一把再说:添加连接选项:
2 G; v5 j( _6 D- ^/align:16(这个大小已经是能够设定的最小的了)。看看结果:1,408Bytes。厉1 m( V$ A- h- t
害,现在代码更小了。
9 F: q5 n" S. v- C3 K5.3 现在回想起来,执行文件大小有数据段,执行代码段等等,如果把这些段都合
2 A" g  }' F  }  p5 X$ c并起来,是不是就会把段之间的冗余有减小了呢?再试试看:添加选项:
% J6 f: n6 |& W- c1 s: z, i0 u8 ^/merge:.data=.text /merge:.rdata=.text。再看看文件大小:1,328bytes。真的
! f5 a, [8 T6 f8 k$ I! M2 M+ g' e很不错了。, d. j8 L) q  p3 b

' M# Z7 B9 Z* z+ j% C6、刚才的设定确实不错,似乎达到了我们想要的极限了。但是回头想一下,如果) I) t( ^7 a& Y
没有CRT库的话,会不会更小了?实际上确实这样。添加连接选项: /entry:
! M$ h  [& Z; M" N& D7 U( ]/ Mmain,把入口地址直接指向我们的main函数看看。得到592Bytes。
: B# n( e. Y3 v$ }
( y4 j9 F3 j  e3 j9 ]; ^. e最终我们得到我们最后的大小592Bytes了。我想这也许是我们通过编译器能够编译  [# m+ }6 S( a' Z( Z/ k
出来的最小的代码了。9 g0 M% }' m4 |# a

6 [. K8 N" u1 e9 ?) h# i% M结论:
& E; c0 j4 K3 Q* R) Q* ~2 t通过上述的步骤,我们了解了如何修改那些编译连接选项来达到执行文件瘦身的目9 t2 g+ Z/ m; s! y3 i0 v% P
的。但是,通常来讲,在我们的Release文件当中,并不需要如此小的执行文件。
& y( O9 K, ]4 k: X5 }/ D6 c$ G如果想达到瘦身的目的,修改为library:MutiThreaded Dll和添加/opt:nowin98已
* Q0 ~6 @" s. C5 V5 _  r& u经是很好的选择了。其他别的选项在编译的时候或多或少的有警告出现,而且,带
: }/ ^$ k5 T" d1 K1 j8 a有那些编译选项编出来的执行文件也不一定在各个平台上能够适用。5 u. W. x$ u& q- O- @
6 e! ~6 f! d. H( d9 C4 j4 P2 I
另外:如果你的执行文件即使通过了这些设定还是比较大的话,也可以通过一些
+ N) X! g" R. P  g2 ~) eEXE文件压缩工具来进行压缩。比如UPX等等。在此不再细说了。
$ Q$ j( V0 T0 B9 }$ N
3 X% i, ^1 F% A0 [3 ?以上部分的不足之处,还请多多指正。
发表于 2006-10-3 13:00:07 | 显示全部楼层
谢谢楼主
回复

使用道具 举报

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

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-9-26 10:58 , Processed in 0.013785 second(s), 4 queries , Redis On.

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

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