目录
一、通过DLL文件实现函数共有
二、通过调用 _stdcall 来减少程序文件的大小
MS-DOC,最初的版本可以在128kb的内存上运行程序,但是现在想要Windows运行流畅至少需要512MB的内存,但通常往往是不够的
很多人认为可以使用虚拟内存来解决内存不足的情况,而虚拟内存确实能够在内存不足的时候提供补充,但是使用虚拟内存的Page In 和 Page Out 通常伴随着低速的磁盘访问,这是一种得不偿失的表现。所以虚拟内存无法从根本上解决内存不足的情况
为了从根本上解决内存不足的情况,要么是增加内存的容量,加内存条;要么优化应用程序,使其尽可能变小。第一种建议往往要需要衡量口袋的银子,所以我们只关注第二种情况
注意:以下的篇幅会涉及到C语言的介绍,是每个程序员(不限语言)都需要知道和了解的知识
一、通过DLL文件实现函数共有
DLL(Dynamic Link Library)文件,是一种 动态链接库 文件,顾名思义,是在程序运行时可以动态加载 Library(函数和数据的集合)的文件。此外,多个应用可以共有同一个DLL文件,而通过共有一个DLL文件则可以达到节约内存的效果
MyFunc()
静态链接导致内存利用率下降:
为了改变这一点,使用DLL文件而不是应用程序的执行文件(EXE文件)。因为同一个DLL文件内容在运行时可以被多个应用共有,因此内存中存放函数MyFunc() 的程序就只有一个
使用动态链接DDL改善内存使用:
Windows操作系统其实就是无数个DLL文件的集合体。有些应用在安装时,DLL文件也会被追加,应用程序通过这些DLL文件来运行,既可以节约内存,也可以在不升级EXE文件的情况下,通过升级DLL文件就可以完成更新
二、通过调用 _stdcall 来减少程序文件的大小
通过调用 _stdcoll
standard call(标准调用)的缩写。Windows提供的DLL文件内的函数,基本上都是通过 _stdcall 调用方式来完成的,这主要是为了节约内存。另一方面,用C语言编写的程序默认都不是 _stdcall。C语言特有的调用方式称为 C 调用。C语言默认不使用 _stdcall 的原因的是因为 C 语言所对应的函数传入参数是可变的,只有函数调用方才能知道到底有多少个参数,在这种情况下,栈的清理作业便无法进行。不过,在C语言中,如果函数的参数和数量固定的话,指定 _stdcall 是没有任何问题的
C语言和Java最主要的区别之一在于C语言需要人为控制释放内存空间
栈清理处理
例如下面代码:
//函数调用方
void main(){
int a;
a = MyFunc(123,456);
}
//被调用方
int MyFunc(int a,int b){
...
}
代码中,从main主函数调用到MyFunc() 方法,按照默认的设定,栈的清理处理会附加在main主函数这一方。在同一程序中,有可能会多次调用,导致MyFunc()会进行多次清理,这就会造成内存的浪费
汇编之后的代码如下:
push 1C8h //将参数 456(= 1C8h)存入栈中
push 7Bh //将参数 123(= 7Bh)存入栈中
call @LTD+15(MyFunc)(00401014) //调用 MyFunc函数
add esp,8 //运行栈清理
push 是往栈中存入数据的指令,pop 是从栈中取出数据的指令。32位CPU中,1次push指令可以存储4个字节(32位)的数据。上述代码由于进行了两次push操作,所以存储了8字节的数据。通过 call 指令来调用函数,调用完成后,栈中存储的数据就不再需要了。于是就通过add esp,8 这个指令,使存储着栈数据的 esp 寄存器前进8位(设定为指向高8位字节的地址),来进行数据清理。由于栈是在各种情况下都可以利用的内存领域,因此使用完毕后有必要将其恢复到原始状态。上述操作就是执行栈的清理工作。另外,在C语言中,函数的返回值,是通过寄存器而非栈来返回的
_stdcall
不同方式的调用方式也不同: