编译原理运行时存储空间的组织和管理 6.ppt

上传人:少林足球 文档编号:3981443 上传时间:2019-10-11 格式:PPT 页数:167 大小:773.06KB
返回 下载 相关 举报
编译原理运行时存储空间的组织和管理 6.ppt_第1页
第1页 / 共167页
编译原理运行时存储空间的组织和管理 6.ppt_第2页
第2页 / 共167页
编译原理运行时存储空间的组织和管理 6.ppt_第3页
第3页 / 共167页
编译原理运行时存储空间的组织和管理 6.ppt_第4页
第4页 / 共167页
编译原理运行时存储空间的组织和管理 6.ppt_第5页
第5页 / 共167页
点击查看更多>>
资源描述

《编译原理运行时存储空间的组织和管理 6.ppt》由会员分享,可在线阅读,更多相关《编译原理运行时存储空间的组织和管理 6.ppt(167页珍藏版)》请在三一文库上搜索。

1、第六章 运行时存储空间的组织和管理,过程的活动 过程的一次执行称为过程的一次活动,第六章 运行时存储空间的组织和管理,过程的活动 过程的一次执行称为过程的一次活动 活动记录 过程的活动需要可执行代码和存放所需信息 的存储空间,后者称为活动记录,第六章 运行时存储空间的组织和管理,过程的活动 过程的一次执行称为过程的一次活动 活动记录 过程的活动需要可执行代码和存放所需信息 的存储空间,后者称为活动记录 本章内容 讨论一个活动记录中的数据安排,第六章 运行时存储空间的组织和管理,过程的活动 过程的一次执行称为过程的一次活动 活动记录 过程的活动需要可执行代码和存放所需信息 的存储空间,后者称为活

2、动记录 本章内容 讨论一个活动记录中的数据安排 程序执行过程中,所有活动记录的组织方式,第六章 运行时存储空间的组织和管理,影响存储分配策略的语言特征 过程能否递归,第六章 运行时存储空间的组织和管理,影响存储分配策略的语言特征 过程能否递归 当控制从过程的活动返回时,局部变量的值是否要保留,第六章 运行时存储空间的组织和管理,影响存储分配策略的语言特征 过程能否递归 当控制从过程的活动返回时,局部变量的值是否要保留 过程能否访问非局部变量,第六章 运行时存储空间的组织和管理,影响存储分配策略的语言特征 过程能否递归 当控制从过程的活动返回时,局部变量的值是否要保留 过程能否访问非局部变量 过

3、程调用的参数传递方式,第六章 运行时存储空间的组织和管理,影响存储分配策略的语言特征 过程能否递归 当控制从过程的活动返回时,局部变量的值是否要保留 过程能否访问非局部变量 过程调用的参数传递方式 过程能否作为参数被传递,第六章 运行时存储空间的组织和管理,影响存储分配策略的语言特征 过程能否递归 当控制从过程的活动返回时,局部变量的值是否要保留 过程能否访问非局部变量 过程调用的参数传递方式 过程能否作为参数被传递 过程能否作为结果值传递,第六章 运行时存储空间的组织和管理,影响存储分配策略的语言特征 过程能否递归 当控制从过程的活动返回时,局部变量的值是否要保留 过程能否访问非局部变量 过

4、程调用的参数传递方式 过程能否作为参数被传递 过程能否作为结果值传递 存储块能否在程序控制下动态地分配,第六章 运行时存储空间的组织和管理,影响存储分配策略的语言特征 过程能否递归 当控制从过程的活动返回时,局部变量的值是否要保留 过程能否访问非局部变量 过程调用的参数传递方式 过程能否作为参数被传递 过程能否作为结果值传递 存储块能否在程序控制下动态地分配 存储块是否必须显式地释放,6.1 局部存储分配,6.1.1 过程 过程定义、过程调用、形式参数、实在参数、活动的生存期,6.1 局部存储分配,6.1.2 名字的作用域和绑定 名字的作用域 一个声明起作用的程序部分称为该声明的作用域 即使一

5、个名字在程序中只声明一次,该名字在程序运行时也可能表示不同的数据对象,6.1 局部存储分配,从名字到值的两步映射,6.1 局部存储分配,从名字到值的两步映射 环境把名字映射到左值,而状态把左值映射到右值,6.1 局部存储分配,从名字到值的两步映射 环境把名字映射到左值,而状态把左值映射到右值 赋值改变状态,但不改变环境,6.1 局部存储分配,从名字到值的两步映射 环境把名字映射到左值,而状态把左值映射到右值 赋值改变状态,但不改变环境 过程调用改变环境,6.1 局部存储分配,从名字到值的两步映射 环境把名字映射到左值,而状态把左值映射到右值 赋值改变状态,但不改变环境 过程调用改变环境 如果环

6、境将名字x映射到存储单元s,我们就说x被绑定到s,6.1 局部存储分配,静态概念和动态概念的对应,6.1 局部存储分配,静态概念和动态概念的对应,6.1 局部存储分配,静态概念和动态概念的对应,6.1 局部存储分配,6.1.3 活动记录 一般的活动记录的布局,6.1 局部存储分配,6.1.4 局部数据的安排 字节是可编址内存的最小单位,6.1 局部存储分配,6.1.4 局部数据的安排 字节是可编址内存的最小单位 变量所需的存储空间可以根据其类型而静态确定,6.1 局部存储分配,6.1.4 局部数据的安排 字节是可编址内存的最小单位 变量所需的存储空间可以根据其类型而静态确定 一个过程所声明的局

7、部变量,按这些变量声明时出现的次序,在局部数据域中依次分配空间,6.1 局部存储分配,6.1.4 局部数据的安排 字节是可编址内存的最小单位 变量所需的存储空间可以根据其类型而静态确定 一个过程所声明的局部变量,按这些变量声明时出现的次序,在局部数据域中依次分配空间 局部数据的地址可以用相对于某个位置的地址来表示,6.1 局部存储分配,6.1.4 局部数据的安排 字节是可编址内存的最小单位 变量所需的存储空间可以根据其类型而静态确定 一个过程所声明的局部变量,按这些变量声明时出现的次序,在局部数据域中依次分配空间 局部数据的地址可以用相对于某个位置的地址来表示 数据对象的存储安排还有一个对齐问

8、题,6.1 局部存储分配,在SPARC/Solaris工作站上下面两个结构的size分别是24和16,为什么不一样? typedef struct _a typedef struct _b char c1; char c1; long i; char c2; char c2; long i; double f; double f; a; b;,6.1 局部存储分配,在SPARC/Solaris工作站上下面两个结构的size分别是24和16,为什么不一样? typedef struct _a typedef struct _b char c1; 0 char c1; 0 long i; 4 ch

9、ar c2; 1 char c2; 8 long i; 4 double f; 16 double f; 8 a; b;,6.1 局部存储分配,在X86/Linux机器的结果和SPARC/Solaris工作站不一样,是20和16。 typedef struct _a typedef struct _b char c1; 0 char c1; 0 long i; 4 char c2; 1 char c2; 8 long i; 4 double f; 12 double f; 8 a; b;,6.1 局部存储分配,6.1.5 程序块 本身含有局部变量声明的语句 可以嵌套 最接近的嵌套作用域规则 并

10、列程序块不会同时活跃 并列程序块的变量可以重叠分配,6.1 局部存储分配,main() / begin of B0 / int a = 0; int b = 0; / begin of B1 / int b = 1; / begin of B2 / int a = 2; / end of B2 / / begin of B3 / int b = 3; / end of B3 / / end of B1 / / end of B0 /,6.1 局部存储分配,main() / begin of B0 / int a = 0; int b = 0; / begin of B1 / int b = 1

11、; / begin of B2 / int a = 2; / end of B2 / / begin of B3 / int b = 3; / end of B3 / / end of B1 / / end of B0 /,6.1 局部存储分配,main() / begin of B0 / int a = 0; int b = 0; / begin of B1 / int b = 1; / begin of B2 / int a = 2; / end of B2 / / begin of B3 / int b = 3; / end of B3 / / end of B1 / / end of

12、B0 /,6.2 全局栈式存储分配,介绍程序运行时所需的各个活动记录在存储空间的分配策略,6.2 全局栈式存储分配,介绍程序运行时所需的各个活动记录在存储空间的分配策略 描述过程的目标代码怎样访问绑定到局部名字的存储单元,6.2 全局栈式存储分配,介绍程序运行时所需的各个活动记录在存储空间的分配策略 描述过程的目标代码怎样访问绑定到局部名字的存储单元 介绍三种分配策略 静态分配策略,6.2 全局栈式存储分配,介绍程序运行时所需的各个活动记录在存储空间的分配策略 描述过程的目标代码怎样访问绑定到局部名字的存储单元 介绍三种分配策略 静态分配策略 栈式分配策略,6.2 全局栈式存储分配,介绍程序运

13、行时所需的各个活动记录在存储空间的分配策略 描述过程的目标代码怎样访问绑定到局部名字的存储单元 介绍三种分配策略 静态分配策略 栈式分配策略 堆式分配策略,6.2 全局栈式存储分配,6.2.1 运行时内存的划分,6.2 全局栈式存储分配,静态分配 名字在程序被编译时绑定到存储单元,不需要运行时的任何支持,6.2 全局栈式存储分配,静态分配 名字在程序被编译时绑定到存储单元,不需要运行时的任何支持 绑定的生存期是程序的整个运行期间,6.2 全局栈式存储分配,静态分配给语言带来限制 递归过程不被允许,6.2 全局栈式存储分配,静态分配给语言带来限制 递归过程不被允许 数据对象的长度和它在内存中位置

14、的限制,必须是在编译时可以知道的,6.2 全局栈式存储分配,静态分配给语言带来限制 递归过程不被允许 数据对象的长度和它在内存中位置的限制,必须是在编译时可以知道的 数据结构不能动态建立,6.2 全局栈式存储分配,C语言程序的外部变量和程序中出现的常量 都可以静态分配 声明在函数外面 外部变量 静态分配 静态外部变量 静态分配 声明在函数里面 静态局部变量 也是静态分配 自动变量 不能静态分配,6.2 全局栈式存储分配,6.2.2 活动树和运行栈 活动树:用树来描绘控制进入和离开活动的方式,6.2 全局栈式存储分配,活动树的特点 每个结点代表某过程的一个活动 根结点代表主程序的活动 结点a是结

15、点b的父结点,当且仅当控制流从a的活动进入b的活动 结点a处于结点b的左边,当且仅当a的生存期先于b的生存期,6.2 全局栈式存储分配,当前活跃着的过程活动可以保存在一个栈中 控制栈的内容:m, q (1, 9), q (1, 3), q (2, 3),6.2 全局栈式存储分配,运行栈:把控制栈中的信息拓广到包括过程 活动所需的所有局部信息(即活动记录),6.2 全局栈式存储分配,运行栈:把控制栈中的信息拓广到包括过程 活动所需的所有局部信息(即活动记录),m,6.2 全局栈式存储分配,运行栈:把控制栈中的信息拓广到包括过程 活动所需的所有局部信息(即活动记录),6.2 全局栈式存储分配,运行

16、栈:把控制栈中的信息拓广到包括过程 活动所需的所有局部信息(即活动记录),6.2 全局栈式存储分配,运行栈:把控制栈中的信息拓广到包括过程 活动所需的所有局部信息(即活动记录),6.2 全局栈式存储分配,6.2.3 调用序列 过程调用和过程返回都需要执行一些代码来管理活动记录栈,保存或恢复机器状态等,6.2 全局栈式存储分配,6.2.3 调用序列 过程调用和过程返回都需要执行一些代码来管理活动记录栈,保存或恢复机器状态等 过程调用序列 过程调用时执行的分配活动记录,把信息填入它的域中的代码,6.2 全局栈式存储分配,6.2.3 调用序列 过程调用和过程返回都需要执行一些代码来管理活动记录栈,保

17、存或恢复机器状态等 过程调用序列 过程调用时执行的分配活动记录,把信息填入它的域中的代码 过程返回序列 过程返回时执行的恢复机器状态,释放活动记录,使调用过程能够继续执行的代码,6.2 全局栈式存储分配,过程调用和过程返回都需要执行一些代码来管理活动记录栈,保存或恢复机器状态等 过程调用序列 过程调用时执行的分配活动记录,把信息填入它的域中的代码 过程返回序列 过程返回时执行的恢复机器状态,释放活动记录,使调用过程能够继续执行的代码 调用序列和返回序列常常都分成两部分,分处于调用过程和被调用过程中,6.2 全局栈式存储分配,即使是同一种语言,过程调用序列、返回序列和活动记录中各域的排放次序,也

18、会因实现而异 设计这些序列和活动记录 的一些原则,6.2 全局栈式存储分配,即使是同一种语言,过程调用序列、返回序列和活动记录中各域的排放次序,也会因实现而异 设计这些序列和活动记录 的一些原则 以活动记录中间的某个 位置作为基地址,6.2 全局栈式存储分配,即使是同一种语言,过程调用序列、返回序列和活动记录中各域的排放次序,也会因实现而异 设计这些序列和活动记录 的一些原则 以活动记录中间的某个 位置作为基地址 长度能较早确定的域放在 活动记录的中间,6.2 全局栈式存储分配,即使是同一种语言,过程调用序列、返回序列和活动记录中各域的排放次序,也会因实现而异 设计这些序列和活动记录 的一些原

19、则 一般把临时数据域放在 局部数据域的后面,6.2 全局栈式存储分配,即使是同一种语言,过程调用序列、返回序列和活动记录中各域的排放次序,也会因实现而异 设计这些序列和活动记录 的一些原则 一般把临时数据域放在 局部数据域的后面 把参数域和可能有的返回 值域放在紧靠调用者活动 记录的地方,6.2 全局栈式存储分配,即使是同一种语言,过程调用序列、返回序列和活动记录中各域的排放次序,也会因实现而异 设计这些序列和活动记录 的一些原则 用同样的代码来执行各个 活动的保存和恢复,6.2 全局栈式存储分配,调用者和被调用者之间的任务划分,6.2 全局栈式存储分配,过程p调用过程q的调用序列 p计算实参

20、,依次放入栈顶,并在栈顶留出放返回值的空间。top_sp的值在此过程中被改变 p把返回地址和当前base_sp的值存入q的活动记录中,建立q的访问链,增加base_sp的值 q保存寄存器的值和其它机器状态信息 q根据局部数据域和临时数据域的大小增加top_sp的值,初始化它的局部数据,并开始执行过程体,6.2 全局栈式存储分配,调用者和被调用者之间的任务划分,6.2 全局栈式存储分配,过程p调用过程q的返回序列 q把返回值置入邻近p的活动记录的地方 q对应调用序列的步骤(4),减小top_sp的值 q恢复寄存器(包括base_sp)和机器状态,返回p p根据参数个数与类型和返回值类型调整top

21、_sp,然后取出返回值,6.2 全局栈式存储分配,调用者和被调用者之间的任务划分,6.2 全局栈式存储分配,过程的参数个数可变的情况 函数返回值改成用寄存器传递 编译器产生将这些参数逆序进栈的代码 被调用函数能准确地知道第一个参数的位置 被调用函数根据第一个参数到栈中取第二、第三个参数等等,6.2 全局栈式存储分配,调用者和被调用者之间的任务划分,6.2 全局栈式存储分配,6.2.4 栈上可变长数据 活动记录的长度在编译时不能确定的情况 局部数组的大小要等到过程激活时才能确定 在活动记录中为这样的数组分别存放数组指针的单元 运行时,这些指针指向分配在栈顶的存储空间,6.2 全局栈式存储分配,6

22、.2 全局栈式存储分配,6.2.5 悬空引用 悬空引用:引用某个已被释放的存储单元,6.2 全局栈式存储分配,6.2.5 悬空引用 悬空引用:引用某个已被释放的存储单元 main() | int dangle ( ) | int q; | int j = 20; q = dangle ( ); | return | ,6.3 非局部名字的访问,本节介绍 无过程嵌套的静态作用域(C语言) 有过程嵌套的静态作用域(Pascal语言) 动态作用域(Lisp语言),6.3 非局部名字的访问,6.3.1 无过程嵌套的静态作用域 过程体中的非局部引用可以直接使用静态确定的地址,6.3 非局部名字的访问,6

23、.3.1 无过程嵌套的静态作用域 过程体中的非局部引用可以直接使用静态确定的地址 局部变量在栈顶的活动记录中,可以通过base_sp指针来访问,6.3 非局部名字的访问,6.3.1 无过程嵌套的静态作用域 过程体中的非局部引用可以直接使用静态确定的地址 局部变量在栈顶的活动记录中,可以通过base_sp指针来访问 无须深入栈中取数据,无须访问链,6.3 非局部名字的访问,6.3.1 无过程嵌套的静态作用域 过程体中的非局部引用可以直接使用静态确定的地址 局部变量在栈顶的活动记录中,可以通过base_sp指针来访问 无须深入栈中取数据,无须访问链 过程可以作为参数来传递,也可以作为结果来返回,6

24、.3 非局部名字的访问,6.3.2 有过程嵌套的静态作用域 sort readarray exchange quicksort partition,6.3 非局部名字的访问,6.3.2 有过程嵌套的静态作用域 过程嵌套深度 sort 1 readarray 2 exchange 2 quicksort 2 partition 3,6.3 非局部名字的访问,6.3.2 有过程嵌套的静态作用域 过程嵌套深度 sort 1 readarray 2 exchange 2 quicksort 2 partition 3 变量的嵌套深度:它的声明所在过程的嵌套 深度作为该名字的嵌套深度,6.3 非局部名字

25、的访问,寻找非局部名字存储单元的访问链,6.3 非局部名字的访问,假定过程p的嵌套深度为np,它引用嵌套深度 为na的变量a,na np。如何访问a的存储单元 sort 1 readarray 2 exchange 2 quicksort 2 partition 3,6.3 非局部名字的访问,假定过程p的嵌套深度为np,它引用嵌套深度 为na的变量a,na np。如何访问a的存储单元 从栈顶的活动记录开始,追踪访问链np na次,6.3 非局部名字的访问,假定过程p的嵌套深度为np,它引用嵌套深度 为na的变量a,na np。如何访问a的存储单元 从栈顶的活动记录开始,追踪访问链np na次

26、到达a的声明所在过程的活动记录,6.3 非局部名字的访问,假定过程p的嵌套深度为np,它引用嵌套深度 为na的变量a,na np。如何访问a的存储单元 从栈顶的活动记录开始,追踪访问链np na次 到达a的声明所在过程的活动记录 访问链的追踪用间接操作就可完成,6.3 非局部名字的访问,访问非局部名字的存储单元,sort readarray exchange quicksort partition,6.3 非局部名字的访问,过程p对变量a访问时,a的地址由下面的二元 组表示: (np na,a在活动记录中的偏移),6.3 非局部名字的访问,建立访问链 假定嵌套深度为np的过程p调用嵌套深度为n

27、x 的过程x np nx的情况 sort 1 readarray 2 exchange 2 quicksort 2 partition 3,6.3 非局部名字的访问,建立访问链 假定嵌套深度为np的过程p调用嵌套深度为nx 的过程x np nx的情况 x肯定就声明在p中,6.3 非局部名字的访问,建立访问链 假定嵌套深度为np的过程p调用嵌套深度为nx 的过程x np nx的情况 x肯定就声明在p中 被调用过程的访问链必须指向调用过程的活动记录的访问链,6.3 非局部名字的访问,建立访问链,sort readarray exchange quicksort partition,6.3 非局部名

28、字的访问,建立访问链 假定嵌套深度为np的过程p调用嵌套深度为nx 的过程x np nx的情况 sort 1 readarray 2 exchange 2 quicksort 2 partition 3,6.3 非局部名字的访问,建立访问链 假定嵌套深度为np的过程p调用嵌套深度为nx 的过程x np nx的情况 p和x的嵌套深度分别为1,2,nx 1的外围过程肯定相同,6.3 非局部名字的访问,建立访问链 假定嵌套深度为np的过程p调用嵌套深度为nx 的过程x np nx的情况 p和x的嵌套深度分别为1,2,nx 1的外围过程肯定相同 追踪访问链np nx + 1次,到达了静态包围x和p的且

29、离它们最近的那个过程的最新活动记录,6.3 非局部名字的访问,建立访问链 假定嵌套深度为np的过程p调用嵌套深度为nx 的过程x np nx的情况 p和x的嵌套深度分别为1,2,nx 1的外围过程肯定相同 追踪访问链np nx + 1次,到达了静态包围x和p的且离它们最近的那个过程的最新活动记录 所到达的活动记录就是x的活动记录中的访问链应该指向的那个活动记录,6.3 非局部名字的访问,建立访问链,sort readarray exchange quicksort partition,6.3 非局部名字的访问,program param(input, output);(过程作为参数) proc

30、edure b(function h(n: integer): integer); begin writeln(h(2) end b; procedure c; var m: integer; function f(n: integer): integer; begin f := m+n end f; begin m := 0; b(f) end c; begin c end.,6.3 非局部名字的访问,program param(input, output);(过程作为参数) procedure b(function h(n: integer): integer); begin writel

31、n(h(2) end b; procedure c; var m: integer; function f(n: integer): integer; begin f := m+n end f; begin m := 0; b(f) end c; begin c end.,过程作为参数传递时,怎样在该过程被激活时建立它的访问链,6.3 非局部名字的访问,program param(input, output);(过程作为参数) procedure b(function h(n: integer): integer); begin writeln(h(2) end b; procedure c;

32、 var m: integer; function f(n: integer): integer; begin f := m+n end f; begin m := 0; b(f) end c; begin c end.,过程作为参数传递时,怎样在该过程被激活时建立它的访问链 从b的访问链难以建立f的访问链,6.3 非局部名字的访问,program param(input, output);(过程作为参数) procedure b(function h( begin writeln(h(2) end ; procedure c; var m: integer; function f(n: in

33、teger) begin f := m+n end f; begin m := 0; b(f) end c; begin c end.,6.3 非局部名字的访问,program ret (input, output);(过程作为返回值) var f: function (integer): integer; function a: function (integer): integer; var m: integer; function addm (n: integer): integer; begin return m+n end; begin m:= 0; return addm end;

34、 procedure b (g: function (integer): integer); begin writeln ( g(2) end; begin f := a; b(f) end.,6.3 非局部名字的访问,program ret (input, output);(过程作为返回值) var f: function (integer): integer; function a: function (integer): integer; var m: integer; function addm (n: integer): integer; begin return m+n end;

35、begin m:= 0; return addm end; procedure b (g: function (integer): integer); begin writeln ( g(2) end; begin f := a; b(f) end.,6.3 非局部名字的访问,C语言的函数声明不能嵌套,函数不论在什么情况下激活,要访问的数据分成两种情况: 非静态局部变量(包括形式参数),它们分配在活动记录栈顶的那个活动记录中 外部变量(包括定义在其它源文件中的外部变量)和静态的局部变量,它们都分配在静态数据区,6.3 非局部名字的访问,6.3.3 动态作用域 被调用过程的非局部名字a和它在调用

36、过程中引用的是同样的存储单元,6.3 非局部名字的访问,6.3.3 动态作用域 被调用过程的非局部名字a和它在调用过程中引用的是同样的存储单元 新的绑定仅为被调用过程的局部名字建立,这些名字在被调用过程的活动记录中占用的存储单元,6.3 非局部名字的访问,program dynamic(input, output); var r: real; procedure show; begin write(r: 5: 3) end; procedure small; var r: real; begin r := 0.125; show end; begin r := 0.25; show; smal

37、l; writeln; show; small; writeln end.,6.3 非局部名字的访问,program dynamic(input, output); var r: real; procedure show; begin write(r: 5: 3) end; procedure small; var r: real; begin r := 0.125; show end; begin r := 0.25; show; small; writeln; show; small; writeln end.,6.3 非局部名字的访问,program dynamic(input, out

38、put); var r: real; procedure show; begin write(r: 5: 3) end; procedure small; var r: real; begin r := 0.125; show end; begin 静态作用域 r := 0.25; 0.250 0.250 show; small; writeln; 0.250 0.250 show; small; writeln end.,6.3 非局部名字的访问,program dynamic(input, output); var r: real; procedure show; begin write(

39、r: 5: 3) end; procedure small; var r: real; begin r := 0.125; show end; begin 动态作用域 r := 0.25; 0.250 0.125 show; small; writeln; 0.250 0.125 show; small; writeln end.,6.3 非局部名字的访问,实现动态作用域的方法 深访问 用控制链搜索运行栈,寻找包含该非局部名字的第一个活动记录 浅访问 为每个名字在静态分配的存储空间中保存它的当前值 当过程p的新活动出现时,p的局部名字n使用在静态数据区分配给n的存储单元。n的先前值可以保存在p

40、的活动记录中,当p的活动结束时再恢复,6.3 非局部名字的访问,program dynamic(input, output); var r: real; procedure show; begin write(r: 5: 3) end; procedure small; var r: real; begin r := 0.125; show end; begin (绿色表示已执行部分) r := 0.25; show; small; writeln; show; small; writeln end.,6.3 非局部名字的访问,program dynamic(input, output); v

41、ar r: real; procedure show; begin write(r: 5: 3) end; procedure small; var r: real; begin r := 0.125; show end; begin r := 0.25; show; small; writeln; show; small; writeln end.,6.3 非局部名字的访问,program dynamic(input, output); var r: real; procedure show; begin write(r: 5: 3) end; procedure small; var r:

42、 real; begin r := 0.125; show end; begin r := 0.25; show; small; writeln; show; small; writeln end.,6.3 非局部名字的访问,program dynamic(input, output); var r: real; procedure show; begin write(r: 5: 3) end; procedure small; var r: real; begin r := 0.125; show end; begin r := 0.25; show; small; writeln; sho

43、w; small; writeln end.,6.3 非局部名字的访问,program dynamic(input, output); var r: real; procedure show; begin write(r: 5: 3) end; procedure small; var r: real; begin r := 0.125; show end; begin r := 0.25; show; small; writeln; show; small; writeln end.,6.3 非局部名字的访问,program dynamic(input, output); var r: re

44、al; procedure show; begin write(r: 5: 3) end; procedure small; var r: real; begin r := 0.125; show end; begin r := 0.25; show; small; writeln; show; small; writeln end.,6.4 参 数 传 递,6.4.1 值调用 实参的右值传给被调用过程 值调用可以如下实现 把形参当作所在过程的局部名看待,形参的存储单元在该过程的活动记录中,6.4 参 数 传 递,6.4.1 值调用 实参的右值传给被调用过程 值调用可以如下实现 把形参当作所在

45、过程的局部名看待,形参的存储单元在该过程的活动记录中 调用过程计算实参,并把其右值放入形参的存储单元中,6.4 参 数 传 递,6.4.2 引用调用 实参的左值传给被调用过程 引用调用可以如下实现: 把形参当作所在过程的局部名看待,形参的存储单元在该过程的活动记录中 调用过程计算实参,把实参的左值放入形参的存储单元,6.4 参 数 传 递,6.4.2 引用调用 实参的左值传给被调用过程 引用调用可以如下实现: 把形参当作所在过程的局部名看待,形参的存储单元在该过程的活动记录中 调用过程计算实参,把实参的左值放入形参的存储单元 在被调用过程的目标代码中,任何对形参的引用都是通过传给该过程的指针来

46、间接引用实参,6.4 参 数 传 递,6.4.3 换名调用 用实参表达式对形参进行正文替换 procedure swap(var x, y: integer); var temp: integer; begin temp := x; x := y; y := temp end,6.4 参 数 传 递,6.4.3 换名调用 用实参表达式对形参进行正文替换 procedure swap(var x, y: integer); var temp: integer; begin 调用swap(i, ai) temp := x; x := y; y := temp end,6.4 参 数 传 递,6.4

47、.3 换名调用 用实参表达式对形参进行正文替换 procedure swap(var x, y: integer); var temp: integer; begin 调用swap(i, ai) temp := x; temp := i; x := y; i := ai; y := temp ai := temp end,6.5 堆 管 理,堆式分配 堆用来存放生存期不确定的数据 C+和Java允许程序员用new创建对象,它们的生存期没有被约束在创建它们的过程活动的生成期之内 实现内存回收是内存管理器的责任 堆空间的回收有两种不同方式 程序显式释放空间:free(C)或delete(C+) 垃

48、圾收集器自动收集(Java),6.5 堆 管 理,6.5.1 内存管理器 内存管理器把握的基本信息是堆中空闲空间 分配函数 回收函数 内存管理器应具有下列性质 空间有效性:极小化程序需要的堆空间总量 程序有效性:较好地利用内存子系统,使得程序能运行得快一些 低开销:分配和回收操作所花时间在整个程序执行时间中的比例尽量小,6.5 堆 管 理,6.5.2 计算机内存分层,6.5 堆 管 理,6.5.2 计算机内存分层 现代计算机都设计成程序员不用关心内存子系统的细节就可以写出正确的程序 程序的效率不仅取决于被执行的指令数,还取决于执行每条指令需要多长时间 执行一条指令的时间区别非常可观 差异源于硬

49、件技术的基本局限:构造不了大容量的高速存储器 数据以块(缓存行、页)为单位在相邻层次之间进行传送 数据密集型程序可从恰当利用内存子系统中获益,6.5 堆 管 理,6.5.3 程序局部性 大多数程序的大部分时间在执行一小部分代码,并且仅涉及一小部分数据 时间局部性 程序访问的内存单元在很短的时间内可能再次被程序访问 空间局部性 毗邻被访问单元的内存单元在很短的时间内可能被访问,6.5 堆 管 理,6.5.3 程序局部性 从代码本身很难看出哪部分代码会被频繁使用,必须动态调整最快缓存的内容 把最近使用的指令保存在缓存是一种较好的最优化利用内存分层的策略 改变数据布局或计算次序也可以改进程序数据访问的时间和空间局部性,6.5 堆 管 理,6.5.4 手工回收请求 程序员在程序中显式释放堆块来达到回收堆

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 其他


经营许可证编号:宁ICP备18001539号-1