目标程序运行时的存储组织(学时).PPT
文本预览下载声明
* * 第10章 目标程序运行时的存储组织 数据空间的三种使用方法和管理方法 静态存储分配 动态存储分配 栈式动态存储分配 堆式动态存储分配 栈式存储分配的实现 简单栈式存储分配的实现 嵌套过程语言的栈式实现 分程序结构的存储管理 参数传递(传值、传址、过程参数) 过程调用、过程进入和过程返回 10.1 数据空间的使用和管理方法 代码生成之前,编译程序必须设计目标程序的运行环境和数据空间的分配。 目标代码区 静态数据区 Stack heap 数据区 数据空间存储分配: 静态存储分配 动态存储分配 栈式 堆式 一、静态存储分配 如果编译时就能确定目标程序运行中所需的全部数据空间大小,那么在编译时就安排好目标程序运行时的全部数据,并确定每个数据对象的存储位置。 特点: 各段数据对象名的作用域在各段中,同一名字在不同的程序段表示不同的存储单元,不会在不同的程序段之间相互引用和赋值 各数据名所需存储空间大小在编译时就能确定 所有数据名的性质是完全确定的 二、栈式动态存储分配 将整个程序的数据空间设计成一个“栈”。 每调用一个过程,该过程所需的数据空间分配在栈顶 该过程一结束就释放这部分空间 过程所需的数据空间: 存放本过程这次活动中的数据对象。 如:局部变量、参数、临时变量等 用于管理过程活动的记录信息。 如:静态链、动态链、返回地址等 三、堆式动态存储分配 采用堆式动态存储分配的情况: 若一个程序设计语言允许用户在程序运行过程中动态地申请数据空间和退还数据空间。 如:C++中的new和delete 不仅有过程还有进程的程序结构,即空间分配未必服从“先申请后释放”原则。 10.2 栈式存储分配的实现 程序运行时,每进入一个过程,就在栈顶为其分配所需的数据空间;过程结束就释放该过程的数据空间。 一个过程的一次执行所需要的信息,使用一段连续的存储区来管理,这个区 (块)叫做一个过程活动记录AR(Activation Record)或frame(帧)。 一般这个区要记录: 临时工作单元:存放中间结果的临时单元。 局部变量 机器状态信息:保存运行过程前的状态(寄存器值,程序计数器,……) 存取链:可选, 用于非局部量的引用。 控制链:可选, 指向调用者的活动记录,释放栈。 实参 返回地址 一、简单的栈式分配方案 前提:没有分程序结构,过程定义不嵌套,但允许过程的递归调用 实例:P234 图10.7 指针: SP:指向现行过程活动记录的起点 TOP:指向栈顶 注意: 若含有可变数组,过程活动记录的内容增加一项“局部数组的内情向量” 控制链(老SP):指向调用该过程的那个过程最新活动记录的基地址。 二、嵌套过程语言的栈式实现 前提:没有分程序结构,允许过程的嵌套定义,允许过程的递归调用。 主要特点: (语言)一个过程可以引用包围它的任一外层过程所定义的标识符(如变量,数组或过程等)。 (实现)一个过程可以引用它的任一外层过程的最新活动记录中的某些数据。 实例:P236 图10.11 关键技术: 解决对非局部量的引用(存取)。设法跟踪每个外层过程的最新活动记录AR的位置。 跟踪办法: 存取链(如PL/0的SL):在过程活动记录中增加“存取链”,指向定义该过程的直接外过程运行时最新数据段的基地址 图10.14 10.13 10.15 Display表:每进入一个过程后,建立活动记录的同时建立一张“嵌套层次表display” display表举例: 图10.16 三、分程序结构的存储管理 前提:允许分程序结构,允许过程的嵌套定义,允许过程的递归调用。 实例:P240 图10.19 分程序结构中一个声明的作用域: 最近嵌套原则 程序名字的存储分配:P241 图10.20 运行时数据空间的变化情况: 参见:P241 图10.21和P243 图10.23 10.3 参数传递 把实参传递给形参的方法: 传值(值调用) 传址(地址引用) 传名(名字调用) 宏扩展 一、传值 形参被作为函数的局部变量,在被调过程的活动记录中开辟了形参的存储单元。 调用过程时,把实参的值赋值给对应形参的存储单元。 对形式参数的任何运算不影响实参的值。 例如: void swap(int x,int y) { int t; t:=x; x:=y; y:=t; } 图10.25 10.26 二、传址 形参用于存放实参对应的地址。 调用过程时,把实参的地址赋值给对应形参的存储单元。 对形参的运算直接影响实参的值。 例如: void swap(int * x,int * y) { int t; t:= *x; *x:= *y; *y:=t;
显示全部