首页 > 系统相关 >5.4 节约内存的编程方式

5.4 节约内存的编程方式

时间:2023-02-10 21:24:41浏览次数:40  
标签:文件 5.4 函数 编程 DLL 内存 stdcall C语言

由于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

相关文章

  • 5.3 虚拟内存把磁盘作为部分内存来使用
    虚拟内存是指把磁盘的一部分作为假想的内存来使用。这与磁盘缓存是假想的磁盘(实际上是内存)相对,虚拟内存是假想的内存(实际上是磁盘)。通过借助虚拟内存,在内存不足时也可......
  • Java 多线程编程
    Java多线程编程Java给多线程编程提供了内置的支持。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。多线程是多任......
  • 5.1 不读入内存就无法运行
    从都具有存储程序命令和数据这点来看,内存和磁盘的功能是相同的。在计算机的5大部件( 一般把输入装置、输出装置、存储器、运算器和控制器这5种部件设备称为计算机的5大部件......
  • 4.4数组是高效使用内存的基础
       数组是指多个同样数据类型的数据在内存中连续排列的形式。作为数组元素的各个数据会通过连续的编号被区分开来,这个编号称为索引(index)。指定索引后,就可以对该索引......
  • Typora软件的使用、编程与编程语言、计算机基础、五大组成部分、三大核心硬件、操作系
    目录一、Typora软件的下载与使用(1)、软件下载(2)、markdown语法二、编程与编程语言(1)、什么是语言(2)、什么是编程(3)、什么是编程语言三、计算机本质四、计算机五大组成......
  • SpringMVC.三 RESTFul编程风格
    1、RESTFuli简介REST:RepresentationalStateTransfer,.表现层资源状态转移,资源资源是一种看待服务器的方式,即,将服务器看作是由很多离散的资源组成。每个资源是服务器上一......
  • 批处理脚本教程_编程入门自学教程_菜鸟教程-免费教程分享
    教程简介批处理脚本语法-从简单和简单的步骤学习批处理脚本,从基本到高级概念,包括概述,环境,命令,文件,语法,变量,注释,字符串,数组,决策,操作符,日期和时间,输入/输出,返回代码,函数,进......
  • 批处理脚本教程_编程入门自学教程_菜鸟教程-免费教程分享
    教程简介批处理脚本语法-从简单和简单的步骤学习批处理脚本,从基本到高级概念,包括概述,环境,命令,文件,语法,变量,注释,字符串,数组,决策,操作符,日期和时间,输入/输出,返回代码,函数,进......
  • SpringBoot + Disruptor实现高并发内存消息队列
    1.简介  Disruptor是英国外汇交易公司LMAX开发的一个高性能队列,研发的初衷是解决内存队列的延迟问题(在性能测试中发现竟然与I/O操作处于同样的数量级)。基于Disruptor开......
  • 解析极限编程-拥抱变化_V2
    作者:KentBeck目录第一章极限编程定义第二章学习开车第三章价值观、原则和实践第四章价值观(略)第五章原则改进多样性第六章实践(略)第七章基本实践第八章启程......