关于VC6.0的文件体积优化

平时写程序,比较注重的就是文件的大小,当然体积越小越好,不管是存储节省,还是提高效率,都是有好处的。

今天突发奇想,去研究研究这方面,假设各种体积优化都是有好处的,那MS为什么不这么做呢?

下面就是我的个人见解了,一个一个来看。

------------------------

#pragma comment(linker, "/ENTRY:xxx")

这一句的意思是指定入口函数,适用于非MFC程序(当然UNICODE的MFC程序也得有这句话,不考虑)。

不管是DLL还是EXE,加上这一句话之后生成的文件体积会瞬间减少几十KB。

减少的东西是什么?反汇编分析很明显,可自己动手尝试一下。

下文中的“伪入口”则为不指定入口点反汇编看到的入口函数。

------------

EXE程序:

int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPCTSTR lpCmdLine, int nCmdShow);

这句话大家肯定熟悉,是否指定入口点对WinMain的参数有决定性的影响。

细心的人会发现,不指定入口点,nCmdShow总是为SW_SHOWDEFAULT,hPrevInstance总是为NULL。

不指定,则各个参数正常,指定之后,各个参数则全部异常。

那么真实情况是WinMain的参数是由“伪入口”传入的,“伪入口”调用了GetModuleHandle和GetCommandLine,并作为参数传递给WinMain,其余两个参数为固定值。WinMain是作为一个主线程的函数,也就是被系统调用的CreateThread所创建,CreateThread只支持一个PVOID参数,所以我感觉WinMain的参数纯粹就是忽悠人的,一旦指定了入口点,取参数的时候可能会引起异常,导致崩溃。参数是在堆栈中的,但是反汇编发现,堆栈里都是乱七八糟的,并不是真正的参数,而且栈顶指向的是ExitThread的地址。

如果指定了入口点,并且在WinMain中创建了其他线程,那么当函数使用return返回的时候,进程并不会退出。

所以,想使用这一句优化指令,必须受到以下限制:

1.不能使用参数,用函数获取。

2.不能使用return来退出进程,要使用ExitProcess(除非你并不那么要求)。

3.不能调用任何C运行库函数(原因后面讲)。

做到了以上几点,你就可以大胆放心的加上这一句优化指令了,享受体积缩小的乐趣吧。

------------

DLL程序:

BOOL WINAPI DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID);

指定入口点之后,反汇编看到的代码确实是DllMain函数,而且堆栈中的参数都是正确的。

这就说明DllMain之前还有代码,但是并不在自身程序中(在哪里我们不必关心)。

那么,“伪入口”都做了什么?还是暂时不讲。

栈顶也不是ExitThread函数的地址了,而是一段系统代码,有兴趣的朋友可以跟踪看看。

同样的,想使用这一句优化指令,必须受到以下限制:

1.不能调用任何C运行库函数。

就一条限制,做到了就可以使用优化指令了。

------------

上面两种类型程序,在指定了入口点的时候都不能调用C运行库函数,这是因为“伪入口”做了初始化C运行库的操作,因为对于C运行库的函数来说,每一个线程都有一份独立的“全局变量”,没有“伪入口”去调用C运行库的函数肯能会发生异常。

至于所谓线程中独立的“全局变量”,去找找资料,我说不清楚。

------------------------

#pragma comment(lib, "msvcrt.lib")

这一句优化也能使程序缩小好多,这类似于MFC程序中“使用共享DLL”和“使用静态DLL”之间的关系。

不做优化的时候调用C运行库函数大部分是由自身代码实现的,典型的例子是memset函数,反汇编一看就明白。

做优化的时候函数全部强制调用外部函数,特点表现在import table上。

做不做优化无所谓,至于优缺点,个人没有看法,

不过我是不喜欢过于依赖外部函数,MS既然那么做了,还是为了程序自身的兼容性,毕竟C运行库函数目前为止有了好几个版本,什么msvcrt.dll/msvcrt80.dll/msvcrt100.dll他们之间肯定有差异,所以个人建议还是自己实现的好(不优化),又不要你自己敲代码,怕啥。

------------------------

#pragma comment(linker, "/OPT:NOWIN98")

这句话使得程序不再兼容Windows 98系统,对于目前的形式来讲,除非特定要求,这句话大可加上,体积也会缩小很多。

特点表现在PE结构中IMAGE_OPTIONAL_HEADER的SectionAlignment成员。

优化的时候SectionAlignment为0x200,不优化的时候SectionAlignment为0x1000。

SectionAlignment的意思是区段的数据对其粒度,98系统支持的粒度是0x1000的整数倍,NT以上系统支持的是0x200的整数倍。

也就是说如果一个区段使用了0x201个字节,那么这个区段占用的数据空间是0x400字节(优化后)。

所以,优化之后,可以减少很多不必要的空间,因为默认是支持Windows 98的,SectionAlignment为0x1000。

------------------------

至于其他优化指令,大多没有什么明显的效果,暂不考虑。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值