运行环境
程序运行时的存储组织
存储分配策略
在运行时存储代码的划分一般为:
其中除了目标代码之后,其余三种数据空间采用的存储分配策略是不同的:
- 静态存储分配
- 栈式存储分配
- 堆式存储分配
静态存储分配
使用静态存储分配的条件式在编译时源程序中声明的各种数据对象所需的存储空间的大小可以确定。
因此在编译时,为静态存储分配的变量分配固定的存储空间:
- 每个过程的活动记录的大小及位置
- 活动记录中每一个名字所占用存储空间的大小及位置
- 数据对象的地址可以生成在目标代码中
使用静态存储分配时,名字的左值在运行期间时保存不变的。
使用静态存储分配对于源程序有一定的限制:
- 数据对象的大小和位置必须在编译时可以确定
- 不允许出现过程递归调用
- 不能建立动态的数据结构
栈式存储分配
存储空间按照栈的方式组织:
- 活动开始的时候,活动相对应的活动记录入栈。局部变量的存储空间分配在活动记录中,同一过程中声明的名字在不同的活动中绑定到不同的存储空间中。
- 活动结束时,活动记录出栈,分配给局部名字的存储空间被释放,名字的值丢失不再可用。
在栈式存储分配中存在调用序列和返回序列:
-
调用序列:目标程序中实现控制从调用程序进入被调用程序的一段代码。
用于实现活动记录的入栈和控制的转移。
-
返回序列:目标程序中实现控制从被调用过程返回到调用过程的一段代码。
用于实现活动记录的出栈和控制的转移。
非局部名字的访问
如何处理非局部名字的应用取决于作用域规则:
- 静态作用域规则:词法作用域规则、最近嵌套规则:由程序中名字的声明的位置决定
- 动态作用域规则:由运行时最近的活动决定应用到一个名字上的声明
对于非局部名字的访问通过访问链来实现,因此关键是如何创建、使用、维护访问链。
程序块
程序块时符合语句的基本结构:
begin
声明语句
语句序列
end
块之间的关系可以使并列和嵌套。