由于Windows具有多任务功能,在巨大的Windows操作系统中可以同时运行多个应用,因此,即使是512MB的内存,有时也无法保证流畅运行。Windows操作系统经常为内存不足所困。
像Windows这样,窗口的菜单及图表等都可以进行可视化操作的方式称为图形用户界面。Windows的前身MS-DOS操作系统,是由键盘输入命令来进行操作的CLI(命令行界面)。
虚拟内存也确实能避免因内存不足导致的应用无法启动。不过,由于使用虚拟内存时发生的Page In和Page Out往往伴随着低速的磁盘访问,因此在这个过程中应用的运行会变得迟钝起来(在操作应用的过程中硬盘访问灯一直亮着,这时正在进行Page In和Page Out)。
为了从根本上解决内存不足的问题,需要增加内存的容量,或者尽量把运行的应用文件变小。虽然增加内存容量更为便捷,但是花费也高。
把应用文件变小的编程方法:
(1)通过DLL文件实现函数共有
DLL文件:是在程序运行时可以动态加载Library(函数和数据的集合)的文件。多个应用可以共有同一个DLL文件,而通过共有同一个DLL文件则可以达到节约内存的效果。
例如,假设我们编写了一个具有某些处理功能的函数MyFunc()。应用A和应用B都会使用这个函数。在各个应用的运行文件中内置函数 MyFunc()(这个称为Static Link,静态链接)后同时运行这两个应用,内存中就存在了具有同一函数的两个程序。但这会导致内存的利用效率降低。所以,有两个同样的函数,还是有点浪费,如下图:
由于同一个DLL文件的内容在运行时可以被多个应用共有,因此内存中存在函数MyFunc()的程序就只有1个。这样一来,内存的利用效率也就提高了。
Windows中,可以执行的应用文件的扩展名是.exe,这样的文件就称为EXE文件。exe是executable(可执行)的略写。另一方面,DLL文件的扩展名为.dll。
Windows的操作系统本身也是多个DLL文件的集合体。有时在安装新应用时,DLL文件也会被追加。应用则会通过利用这些DLL文件的功能来运行。
利用多个DLL文件的一个原因是可以节约内存。而且DLL文件还有一个优点是在不变更EXE文件的情况下,只通过升级DLL文件就可以更新。
(2)通过调用_stdcall来减小程序文件的大小
通过调用_stdcall”来减小程序文件的方法,是用C语言编写应用时可以利用的高级技巧。
_stdcall是standard call(标准调用)的略称。Windwos提供的DLL文件内的函数,基本上都是_stdcall调用方式。这主要是为了节约内存。另一方面,用C语言编写的程序内的函数,默认设置都不是_stdcall。C语言特有的调用方式称为C调用。C语言之所以默认不使用_stdcall,是因为C语言所对应的函数的传入参数是可变的(可以设定任意参数),只有函数调用方才能知道到底有多少个参数,而这种情况下,栈的清理作业便无法进行。不过,在C语言中,如果函数的参数数量固定的话,指定_stdeall是没有任何问题的。
C语言中,在调用函数后,需要执行栈清理处理指令。
栈清理处理是指把不需要的数据从接收和传递函数的参数时使用的内存上的栈区域中清理出去。该命令不是程序记述的,而是在程序编译时由编译器自动附加到程序中的。编译器默认将该处理附加在函数调用方。
例如,在代码清单5-1中,从函数 main()中调用了函数 MyFunc()。按照默认设定,栈的清理处理会附加在函数main()这一方。在同一个程序中,同样的函数可能会被多次反复调用。而如果是同样的函数,栈清理处理的内容也是一样的。由于该处理是在调用函数一方,因此就会导致同一处理被反复进行。这就造成了内存的浪费。
虽然通过调查编译器生成的机器语言执行文件就可以得知栈清理的处理内容,不过鉴于原始的机器语言不太容易理解,所以这里我们用汇编语言的代码清单将其显示了出来。将代码清单5-1中调用函数MyFunc()的部分用汇编语言来表示,就如代码清单5-2所示。最后1行的处理就是清理处理。
C语言通过栈来传递函数的参数。push是往栈中存入数据的指令。32位CPU中,1次push指令可以存储4个字节的数据。
由于栈是在各种情况下都可以再利用的内存领域,因此使用完毕后有必要将其恢复到原状态。
栈清理处理,比起在函数调用方进行,在反复被调用的函数一方进行时,程序整体要小一些。这时所使用的就是_stdcall。在函数前加上_stdcall,就可以把栈清理处理变为在被调用函数一方进行。
标签:文件,5.4,函数,编程,DLL,内存,stdcall,C语言 From: https://www.cnblogs.com/ttmeng/p/17110317.html