编译原理-7-运行存储分配

目录

1 运行存储分配概述

2 静态存储分配

(1)静态存储分配的限制条件

(2)常用的静态存储分配方法

3 栈式存储分配

4 调用序列和返回序列

5 非局部数据的访问

(1)支持&不支持过程嵌套声明的语言

(2)无&有过程嵌套声明时的数据访问

(3)访问链

6 堆栈存储分配

7 符号表

8 符号表的建立


1 运行存储分配概述

   编译器在工作过程中,必须为源程序中出现的一些 数据对 分配 运行时的存储空间
   对于那些在 编译时刻 就可以确定大小的数据对象,可以在 编译时刻就为它们分配存储空间,这样的分配策略称为 态存储分配
   反之,如果不能在编译时完全确定数据对象的大小,就要 采用 动态存储分配 的策略。即在编译时仅产生各种必要的 信息,而在 运行时刻 ,再动态地分配数据对象的存储空间
      栈式存储分配
      堆式存储分配
静态 动态 分别对应 编译时刻 运行时刻
编译原理-7-运行存储分配_第1张图片
活动记录
使用 过程 ( 函数 方法 ) 作为用户自定义动作的单元的 语言,其编译器通常 以过程为单位分配存储空间
过程体的每次执行称为该过程的一个 活动 ( activation)
过程每执行一次,就为它分配一块连续存储区,用来管理过程一次执行所需的信息,这块连续存储区称为 活动 记录 ( activation record )
编译原理-7-运行存储分配_第2张图片
 

2 静态存储分配

在静态存储分配中,编译器为每个过程确定其活动记 录在目标程序中的位置。 这样,过程中每个名字的存储位置就确定了
因此,这些名字的存储地址可以被编译到目标代码中
过程每次执行时,它的名字都绑定到同样的存储单元

(1)静态存储分配的限制条件

①数组上下界必须是常数
②不允许过程的递归调用
③不允许动态建立数据实体
满足这些条件的语言有 BASIC FORTRAN

(2)常用的静态存储分配方法

①顺序分配法

编译原理-7-运行存储分配_第3张图片

②层次分配法

编译原理-7-运行存储分配_第4张图片

编译原理-7-运行存储分配_第5张图片

3 栈式存储分配

有些语言使用过程、函数或方法作为用户自定义动作的单 元,几乎所有针对这些语言的编译器都把它们的 ( 至少一 部分的 ) 运行时刻存储以 的形式进行管理,称为 栈式存 储分配
当一个过程被 调用 时,该过程的活动记录被 压入 栈;当过 结束 时,该活动记录被 弹出
这种安排不仅允许活跃时段不交叠的多个过程调用之间 享空间 ,而且允许以如下方式为一个过程编译代码:它的 非局部变量的 相对地址总是固定的 ,和过程调用序列无关
活动树
   用来描述程序 运行 期间控制进入和离开各个活动的情况 的树称为 活动树
   树中的每个 结点 对应于一个 活动 根结点 是启动程序执 行的 main过程的活动
   在表示过程p 的某个活动的结点上,其 子结点 对应于被 p 的这次活动 调用 的各个过程的活动。按照这些 活动被调 用的顺序 ,自左向右地显示它们。 一个子结点必须在其右兄弟结点的活动开始之前结束
编译原理-7-运行存储分配_第6张图片
编译原理-7-运行存储分配_第7张图片
每个 活跃的活动 都有一个位于 控制栈 中的 活动记录
活动树的 的活动记录位于 栈底
程序控制所在的活动的记录 位于 栈顶
栈中 全部活动记录的序列 对应于在活动树中 到达当前控制所在的活动结点的路径
 
编译原理-7-运行存储分配_第8张图片

4 调用序列和返回序列

过程 调用 和过程 返回 都需要执行一些 代码 来管理活动记录 栈,保存或恢复机器状态等
调用序列
  实现过程调用的代码段。为一个活动记录在栈中分配空间,并在此记录的字段中填写信息  
返回序列
恢复机器状态,使得调用过程能够在调用结束之后继续执行
   一个调用代码序列中的代码通常被分割到调用过程(调用者)和被调用过程(被调用者)中。返回序列也是如此 
编译原理-7-运行存储分配_第9张图片
变长数据的存储分配
现代程序设计语言 中,在 编译时刻不能确定大小的对象 将被分配在 区。但是,如果它们是 过程的局部对象 ,也 可以将它们分配在 运行时刻栈 中。尽量将对象放置在栈区 的原因:可以 避免 对它们的空间进行 垃圾回收 ,也就 减少 了相应的 开销
只有一个数据对象 局部于某个过程 ,且 当此过程结束时它 变得不可访问 ,才可以使用栈为这个对象分配空间
编译原理-7-运行存储分配_第10张图片

5 非局部数据的访问

编译原理-7-运行存储分配_第11张图片

(1)支持&不支持过程嵌套声明的语言

编译原理-7-运行存储分配_第12张图片

(2)无&有过程嵌套声明时的数据访问

编译原理-7-运行存储分配_第13张图片

编译原理-7-运行存储分配_第14张图片

(3)访问链

静态作用域规则:只要过程b 的声明嵌套在过程 a 声明中,过程 b 就可以访问过程 a中声明的对象
可以在相互嵌套的过程的活动记录之间建立一种称为 访问链 ( Access link ) 的指针,使得内嵌的过程可以访问外层过程中声明的对象
如果过程b 在源代码中 直接嵌套 在过程 a ( b 的嵌套深度 a 的嵌套深度多 1) ,那么 b 任何 活动中的访问链都指 最近的 a的活动
编译原理-7-运行存储分配_第15张图片
编译原理-7-运行存储分配_第16张图片
编译原理-7-运行存储分配_第17张图片

6 堆栈存储分配

堆式存储分配是把连续存储区域分 成块 ,当活动记录或 其它对象需要时就分配
块的释放可以按任意次序进行,所以经过一段时间后, 对可能包含交错的 正在使用 已经释放 的区域
编译原理-7-运行存储分配_第18张图片
编译原理-7-运行存储分配_第19张图片
 

7 符号表

符号表的组织 : 为每个作用域(程序块)建立一个独立的符号表
编译原理-7-运行存储分配_第20张图片
编译原理-7-运行存储分配_第21张图片
编译原理-7-运行存储分配_第22张图片

8 符号表的建立

编译原理-7-运行存储分配_第23张图片
 
编译原理-7-运行存储分配_第24张图片
 
 
 
 

你可能感兴趣的:(编译原理)