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

上传人:laozhun 文档编号:4526675 上传时间:2023-04-26 格式:PPT 页数:167 大小:773.04KB
返回 下载 相关 举报
编译原理运行时存储空间的组织和管理 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 名字的作用域和绑定名字的作用域一个声明起作用的程序部分称为该声明的作用域即使一个名字在程序中只声明一次,该名字在程序运行时也可能表示不同的数据对象,6.1 局部存储分配,从名字到

5、值的两步映射,6.1 局部存储分配,从名字到值的两步映射环境把名字映射到左值,而状态把左值映射到右值,6.1 局部存储分配,从名字到值的两步映射环境把名字映射到左值,而状态把左值映射到右值赋值改变状态,但不改变环境,6.1 局部存储分配,从名字到值的两步映射环境把名字映射到左值,而状态把左值映射到右值赋值改变状态,但不改变环境 过程调用改变环境,6.1 局部存储分配,从名字到值的两步映射环境把名字映射到左值,而状态把左值映射到右值赋值改变状态,但不改变环境 过程调用改变环境如果环境将名字x映射到存储单元s,我们就说x被绑定到s,6.1 局部存储分配,静态概念和动态概念的对应,6.1 局部存储分

6、配,静态概念和动态概念的对应,6.1 局部存储分配,静态概念和动态概念的对应,6.1 局部存储分配,6.1.3 活动记录一般的活动记录的布局,6.1 局部存储分配,6.1.4 局部数据的安排字节是可编址内存的最小单位,6.1 局部存储分配,6.1.4 局部数据的安排字节是可编址内存的最小单位变量所需的存储空间可以根据其类型而静态确定,6.1 局部存储分配,6.1.4 局部数据的安排字节是可编址内存的最小单位变量所需的存储空间可以根据其类型而静态确定一个过程所声明的局部变量,按这些变量声明时出现的次序,在局部数据域中依次分配空间,6.1 局部存储分配,6.1.4 局部数据的安排字节是可编址内存的

7、最小单位变量所需的存储空间可以根据其类型而静态确定一个过程所声明的局部变量,按这些变量声明时出现的次序,在局部数据域中依次分配空间局部数据的地址可以用相对于某个位置的地址来表示,6.1 局部存储分配,6.1.4 局部数据的安排字节是可编址内存的最小单位变量所需的存储空间可以根据其类型而静态确定一个过程所声明的局部变量,按这些变量声明时出现的次序,在局部数据域中依次分配空间局部数据的地址可以用相对于某个位置的地址来表示数据对象的存储安排还有一个对齐问题,6.1 局部存储分配,在SPARC/Solaris工作站上下面两个结构的size分别是24和16,为什么不一样?typedef struct _

8、atypedef struct _bchar c1;char c1;long i;char c2;charc2;long i;double f;double f;a;b;,6.1 局部存储分配,在SPARC/Solaris工作站上下面两个结构的size分别是24和16,为什么不一样?typedef struct _atypedef struct _bchar c1;0 char c1;0long i;4 char c2;1charc2;8 long i;4double f;16 double f;8a;b;,6.1 局部存储分配,在X86/Linux机器的结果和SPARC/Solaris工作站

9、不一样,是20和16。typedef struct _atypedef struct _bchar c1;0 char c1;0long i;4 char c2;1charc2;8 long i;4double f;12 double f;8a;b;,6.1 局部存储分配,6.1.5 程序块本身含有局部变量声明的语句可以嵌套最接近的嵌套作用域规则并列程序块不会同时活跃并列程序块的变量可以重叠分配,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/b

10、egin 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 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

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

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

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

14、结点代表主程序的活动结点a是结点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 全局栈式存储分配,运

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

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

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

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

19、址和当前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)和机器状态,返回pp根据参数个数与类型和返回值类型调整top_sp,然后取出返回值,6.2 全局栈式存储分配,调用者和被调用者之间的任务划分,6.2 全局栈式

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

21、.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.3.1 无过程嵌套的静态作用域过程体中的非局部引用可以直接使用静态确定的地址局部变量在栈顶的活动记录中,可以通过base_sp指针来访问,6.3 非局部名字的访问,

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

23、套的静态作用域过程嵌套深度sort1readarray2exchange2quicksort2partition3,6.3 非局部名字的访问,6.3.2 有过程嵌套的静态作用域过程嵌套深度sort1readarray2exchange2quicksort2partition3变量的嵌套深度:它的声明所在过程的嵌套深度作为该名字的嵌套深度,6.3 非局部名字的访问,寻找非局部名字存储单元的访问链,6.3 非局部名字的访问,假定过程p的嵌套深度为np,它引用嵌套深度为na的变量a,na np。如何访问a的存储单元sort1readarray2exchange2quicksort2partition

24、3,6.3 非局部名字的访问,假定过程p的嵌套深度为np,它引用嵌套深度为na的变量a,na np。如何访问a的存储单元从栈顶的活动记录开始,追踪访问链np na次,6.3 非局部名字的访问,假定过程p的嵌套深度为np,它引用嵌套深度为na的变量a,na np。如何访问a的存储单元从栈顶的活动记录开始,追踪访问链np na次到达a的声明所在过程的活动记录,6.3 非局部名字的访问,假定过程p的嵌套深度为np,它引用嵌套深度为na的变量a,na np。如何访问a的存储单元从栈顶的活动记录开始,追踪访问链np na次到达a的声明所在过程的活动记录访问链的追踪用间接操作就可完成,6.3 非局部名字的

25、访问,访问非局部名字的存储单元,sort readarray exchange quicksort partition,6.3 非局部名字的访问,过程p对变量a访问时,a的地址由下面的二元组表示:(np na,a在活动记录中的偏移),6.3 非局部名字的访问,建立访问链假定嵌套深度为np的过程p调用嵌套深度为nx的过程xnp nx的情况sort1readarray2exchange2quicksort2partition3,6.3 非局部名字的访问,建立访问链假定嵌套深度为np的过程p调用嵌套深度为nx的过程xnp nx的情况x肯定就声明在p中,6.3 非局部名字的访问,建立访问链假定嵌套深度

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

27、肯定相同,6.3 非局部名字的访问,建立访问链假定嵌套深度为np的过程p调用嵌套深度为nx的过程xnp nx的情况p和x的嵌套深度分别为1,2,nx 1的外围过程肯定相同追踪访问链np nx+1次,到达了静态包围x和p的且离它们最近的那个过程的最新活动记录,6.3 非局部名字的访问,建立访问链假定嵌套深度为np的过程p调用嵌套深度为nx的过程xnp nx的情况p和x的嵌套深度分别为1,2,nx 1的外围过程肯定相同追踪访问链np nx+1次,到达了静态包围x和p的且离它们最近的那个过程的最新活动记录所到达的活动记录就是x的活动记录中的访问链应该指向的那个活动记录,6.3 非局部名字的访问,建立

28、访问链,sort readarray exchange quicksort partition,6.3 非局部名字的访问,program param(input,output);(过程作为参数)procedure 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 cend.,6.3 非局部名字的访问,program param(i

29、nput,output);(过程作为参数)procedure 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 cend.,过程作为参数传递时,怎样在该过程被激活时建立它的访问链,6.3 非局部名字的访问,program param(input,output);(过程作为参数)procedure b(function h(n:in

30、teger):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 cend.,过程作为参数传递时,怎样在该过程被激活时建立它的访问链 从b的访问链难以建立f的访问链,6.3 非局部名字的访问,program param(input,output);(过程作为参数)procedure b(function h(begin writeln(h(2)end;procedure c;va

31、r m:integer;function f(n:integer)begin f:=m+n end f;begin m:=0;b(f)end c;begin cend.,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;pro

32、cedure 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;begin m:=0;return addm end;procedur

33、e 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和它在调用过程中引用的是同样的存储单元,6.3 非局部名字的访问,6.3.3 动态作用域被调用过程的非局部名字a和它在

34、调用过程中引用的是同样的存储单元新的绑定仅为被调用过程的局部名字建立,这些名字在被调用过程的活动记录中占用的存储单元,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)

35、;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:real;procedure show;begin write(r:5:3)end;procedure small;var r:real;begin r:=0.125;show end;b

36、egin静态作用域 r:=0.25;0.2500.250 show;small;writeln;0.2500.250 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;0.250 0.125 show;small;writeln;0.250 0.125 show;small;wr

37、iteln end.,6.3 非局部名字的访问,实现动态作用域的方法深访问用控制链搜索运行栈,寻找包含该非局部名字的第一个活动记录浅访问为每个名字在静态分配的存储空间中保存它的当前值当过程p的新活动出现时,p的局部名字n使用在静态数据区分配给n的存储单元。n的先前值可以保存在p的活动记录中,当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;

38、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;show;small;writeln end.,6.3 非局部名字的访问,program dynamic(input

39、,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:real;procedure show;begin write(r:5:3)end;procedure small;var r:real;begin r:=0.125;sh

40、ow 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;show;small;writeln end.,6.3 非局部名字的访问,program dynamic(input,ou

41、tput);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.4 参 数 传 递,6.4.1 值调用实参的右值传给被调用过程 值调用可以如下实现把形参当作所在过程的局部名看待,形参的存储单元在该过程的活动记录中,6.4 参 数 传 递,6.4.1 值调用实参的右值传给被调用过程 值调用可以如下实现把形参当作所在过程的局部名看待,形参

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

43、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.3 换名调用用实参表达式对形参进行正文替换procedure swap(var x,y:intege

44、r);var temp:integer;begin 调用swap(i,ai)temp:=x;temp:=i;x:=y;i:=ai;y:=tempai:=temp end,6.5 堆 管 理,堆式分配堆用来存放生存期不确定的数据 C+和Java允许程序员用new创建对象,它们的生存期没有被约束在创建它们的过程活动的生成期之内实现内存回收是内存管理器的责任堆空间的回收有两种不同方式 程序显式释放空间:free(C)或delete(C+)垃圾收集器自动收集(Java),6.5 堆 管 理,6.5.1 内存管理器内存管理器把握的基本信息是堆中空闲空间 分配函数 回收函数内存管理器应具有下列性质 空间有

45、效性:极小化程序需要的堆空间总量 程序有效性:较好地利用内存子系统,使得程序能运行得快一些 低开销:分配和回收操作所花时间在整个程序执行时间中的比例尽量小,6.5 堆 管 理,6.5.2 计算机内存分层,6.5 堆 管 理,6.5.2 计算机内存分层 现代计算机都设计成程序员不用关心内存子系统的细节就可以写出正确的程序 程序的效率不仅取决于被执行的指令数,还取决于执行每条指令需要多长时间 执行一条指令的时间区别非常可观 差异源于硬件技术的基本局限:构造不了大容量的高速存储器 数据以块(缓存行、页)为单位在相邻层次之间进行传送 数据密集型程序可从恰当利用内存子系统中获益,6.5 堆 管 理,6.

46、5.3 程序局部性大多数程序的大部分时间在执行一小部分代码,并且仅涉及一小部分数据时间局部性 程序访问的内存单元在很短的时间内可能再次被程序访问空间局部性毗邻被访问单元的内存单元在很短的时间内可能被访问,6.5 堆 管 理,6.5.3 程序局部性 从代码本身很难看出哪部分代码会被频繁使用,必须动态调整最快缓存的内容 把最近使用的指令保存在缓存是一种较好的最优化利用内存分层的策略 改变数据布局或计算次序也可以改进程序数据访问的时间和空间局部性,6.5 堆 管 理,6.5.4 手工回收请求程序员在程序中显式释放堆块来达到回收堆块的目的 内存泄漏:没有释放已经引用不到的堆块 只要内存没有用尽,它就不

47、影响程序的正确性 自动无用单元收集通过回收所有无用单元来摆脱内存泄漏悬空引用:引用已经被释放的堆块 过分热心地释放数据对象而引起 悬空引用容易导致不会被捕获的错误,本 章 要 点,影响存储分配策略的语言特征各种存储分配策略,主要了解静态分配和动态栈式分配活动记录中各种数据域的作用和安排非局部数据访问的实现方法各种参数传递方式及其实现堆管理,例 题 1,一个C语言程序及其在X86/Linux操作系统上的编译结果如下。根据所生成的汇编程序来解释程序中四个变量的存储分配、作用域、生存期和置初值方式等方面的区别static long aa=10;short bb=20;func()static lon

48、g cc=30;short dd=40;,例 题 1,.data|.align 4.align 4|.type cc.2,object.type aa,object|.size cc.2,4.size aa,4|cc.2:aa:|.long 30.long 10|.text.globl bb|.align 4.align 2|.globl func.type bb,object|func:.size bb,2|.bb:|movw$40,-2(%ebp).value 20|.,例 题 2,main()char*cp1,*cp2;cp1=12345;cp2=abcdefghij;strcpy(cp

49、1,cp2);printf(cp1=%sncp2=%sn,cp1,cp2);在某些系统上的运行结果是:cp1=abcdefghijcp2=ghij为什么cp2所指的串被修改了?,例 题 2,因为常量串“12345”和“abcdefghij”连续分配在常数区执行前:1 2 3 4 5 0 a b c d e f g h i j 0 cp1 cp2,例 题 2,因为常量串“12345”和“abcdefghij”连续分配在常数区执行前:1 2 3 4 5 0 a b c d e f g h i j 0 cp1 cp2执行后:a b c d e f g h i j 0 f g h i j 0 cp1

50、cp2,例 题 2,因为常量串“12345”和“abcdefghij”连续分配在常数区执行前:1 2 3 4 5 0 a b c d e f g h i j 0 cp1 cp2执行后:a b c d e f g h i j 0 f g h i j 0 cp1 cp2现在的编译器大都把程序中的串常量单独存放在只读数据段中,因此运行时会报错,例 题 3,func(i)long i;long j;j=i-1;func(j);,例 题 3,func(i)func:long i;pushl%ebp 老的基地址指针压栈 movl%esp,%ebp修改基地址指针 long j;subl$4,%esp 为j分

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

当前位置:首页 > 办公文档 > 文秘知识


备案号:宁ICP备20000045号-2

经营许可证:宁B2-20210002

宁公网安备 64010402000987号