资源预览内容
第1页 / 共71页
第2页 / 共71页
第3页 / 共71页
第4页 / 共71页
第5页 / 共71页
第6页 / 共71页
第7页 / 共71页
第8页 / 共71页
第9页 / 共71页
第10页 / 共71页
亲,该文档总共71页,到这儿已超出免费预览范围,如果喜欢就下载吧!
资源描述
第7章 运行环境,知识点:活动记录、控制栈 栈式存储分配 非局部名字的访问 参数传递方式,1,运行环境,程序运行时刻的环境,即运行中程序的信息是怎样存储和访问的。 执行过程中,程序中数据的存取是通过对应的存储单元来进行的。 存储组织与管理 早期的计算机上,存储管理工作是由程序员自己来完成 有了高级语言之后,程序中使用的存储单元都由标识符来表示,它们对应的内存地址由编译程序在编译时或由其生成的目标程序在运行时进行分配。 存储的组织及管理是编译程序要完成的一个复杂而又十分重要的工作。,2,运行环境,7.1 程序运行时的存储组织 7.2 存储分配策略 7.3 访问非局部名字 7.4 参数传递机制 小 结,3,7.1 程序运行时的存储组织,概念:过程与活动 一、程序运行空间的划分 二、控制栈与活动记录 三、作用域及名字绑定,4,概念:过程与活动,过程的定义 一个声明语句 把一个标识符和一个语句联系起来 标识符是过程名,语句是过程体。 过程的分类 过程:没有返回值的过程 函数:有返回值的过程 也可以把函数、一个完整的程序看作过程 过程引用:过程名出现在一个可执行语句中 参数: 形参、实参,5,活动,活动 一个过程的每次执行称为它的一次活动 如果一个过程在执行中,则称它的这次活动是活着的 过程与活动 过程是一个静态概念,活动是一个动态概念 过程与活动之间可以是1:1、1:m的关系 递归过程,同一时刻可能有若干个活动是活着的 每个活动都有自己独立的存储空间/数据空间,P,P,P,P有3个活着的活动,P有2个活着的活动,P有1个活着的活动,6,活动的生存期,程序执行时,过程之间的控制流 是连续的 过程的每一次执行都是从过程体的起点开始,最后控制返回到直接跟随本次调用点的位置。 活动的生存期 过程体的执行中,第一步和最后一步之间的一系列步骤的执行时间 过程P的一次活动的生存期,包括执行过程P所调用的过程的时间,以及这些过程所调用的过程的时间 如果a和b是过程的活动,那么它们的生存期要么是不重叠,要么是嵌套的。 递归过程: 如果一个过程,它的不同活动的生存期可以嵌套,则这个过程是递归的 直接递归、间接递归,7,一、程序运行空间的划分,编译程序在编译源程序时,向操作系统申请一块内存区域,以便被编译程序在其中运行,代码区/ 保存目标代码,静态数据区,控制栈,堆,编译时可以确定代码段的长度, 可以放在一个静态确定的区域内,编译时可确定大小的数据对象,放在静态确 定的区域内,目标地址可以编入目标代码中,用于管理过程的活动、 保存断点的现场信息,用于返回时的恢复,程序控制下进行的动态存储分配, 分配在堆中,如Pascal中new函数,?,8,二、控制栈与活动记录,控制栈:用于保存控制信息的栈。 程序执行过程中使用控制栈来保存活动的生存踪迹及活动的运行环境。 活动记录:一个连续的存储块 记录过程在一次执行中所需要的信息 通常,活动记录分配在控制栈中(像Pascal、C) 当一个过程被调用时,被调用过程的一次新的活动被激活,在栈顶为该活动创建一个新的活动记录来保存其环境信息; 当活动结束,控制从被调用过程返回时,释放该活动记录,使调用过程的活动记录成为栈顶活动记录,即恢复调用过程的执行环境。,9,活动记录的内容,返回值,实参区域,控制链,访问链,机器状态域,局部数据区,临时数据区,存放中间计算结果,在本次活动中,为过程中定义的局部变量 分配的存储空间,保存断点的现场信息,寄存器、PSW等,指向直接外围过程的最近一次活动的活动 记录的指针,用于对非局部名字的访问,指向调用过程的活动记录的指针, 用于本活动结束时的恢复,调用过程提供给本活动的实参值,本活动返回给调用过程的值,根据确定每个域所需空间大小的时间早晚安排其位置。 (1) 早:中间 晚:两头 (2) 用于通信:前面 自己用的:后面,10,活动记录中内容的安排原则,大小能够较早确定的区域放在活动记录的中间,大小较晚才能确定、并且变化较多的区域放在活动记录的两头。 控制链、访问链、机器状态域,是编译器设计的一部分,编译器构造时就可以确定它们的大小,所以把这些区域放在活动记录的中间。 参数域放在前面,便于调用过程进行参数传递,同时,被调用过程也可很方便地进行访问。 返回值域放在最前面,便于调用过程可以根据自己的栈指针访问该区域,取回返回值。 局部数据/临时数据安排在最后,其大小变化不会影响到活动记录中其他数据的存取。并且调用过程也无权访问被调用过程中的局部数据。,11,局部数据的安排,常识: 程序运行时使用连续的存储空间 内存可编址的最小单位是字节 一个机器字由若干个字节组成 一个名字所需存储空间的大小由其类型决定 需多个字节表示的数据对象,存放在连续字节的存储块中,第一个字节的地址作为它的地址 局部数据的安排 局部数据区是在编译过程中检查声明语句时安排的 长度可变的数据对象,放在该区域之外 数据对象的存储安排受目标机器编址限制的影响,12,编址限制的影响,整数加法指令可能要求整数的地址能够被4整除 要求地址对齐 如:x:integer; y:char; z:integer;,为求分配上的全局统一,而多余出来的无用空间叫做填塞(padding),如果char占一个字节,integer占2个字节, x、y、z共需要5个字节。 如果要求从双字节地址分配, 则需要为这三个变量分配6个字节,,13,三、作用域及名字绑定,声明是一个把信息与名字联系起来的语法结构 显式声明(如PASCAL中的声明:var i:integer) 隐含声明(如FORTRAN程序) 在一个程序的不同部分可能有对同一个名字的相互独立的声明 一个声明起作用的程序部分称为该声明的作用域 语言的作用域规则决定了当这样的名字在程序正文中出现时应该使用哪一个声明 Pascal中的名字遵循“最近嵌套原则” 编译过程中,名字的作用域信息记录在符号表中,14,名字的绑定,把名字对应到存储单元的过程 名字与存储单元的对应关系: 1:1 1:m,当environment把一个存储单元S与一个名字X联系起来时,称X受限于S。 S的大小取决于X的类型,一个活动中的名字与其存储单元之间,一个递归过程中的名字与其存储单元之间,名字X 存储单元S S的内容V,environment,state,地址为名字的左值,名字的右值,15,与存储组织与管理有关的其他问题,名字的存储空间如何组织、名字绑定的方法等主要取决于对以下问题的回答: 过程是否可递归? 当控制从过程的一次活动返回时,对局部名字的值如何处理? 过程是否可以引用非局部的名字? 过程调用时如何传递参数? 过程是否可以作为参数传递? 过程可否作为结果被返回? 存储空间能否在程序控制下进行动态分配? 存储空间是否必须显式地归还?,16,7.2 存储分配策略,运行时刻存储空间的划分,除目标代码外,其余三种数据空间采用的存储分配策略是不同的。 静态存储分配:编译时对所有数据对象分配存储空间 栈式存储分配:运行时把存储器作为栈进行管理,数据对象分配在栈中 堆式存储分配:运行时把存储器组织成堆结构,对用户提出的存储空间的申请与归还进行存储分配与回收。,一、静态存储分配 二、栈式存储分配 三、堆式存储分配,17,一、静态存储分配,条件:源程序中出现的各种数据所需要的存储空间的大小在编译时可以确定 存储分配:编译时,为他们分配固定的存储空间 运行时:总是使用这些存储空间 过程每次被激活,同一名字都使用相同的存储空间 允许局部名字的值在活动结束后被保留下来 当控制再次进入时,局部名字的值即上次离开时的值 数据对象: 每个过程的活动记录的位置及大小 记录中每一个名字所占用的存储空间的位置及大小 数据在运行时刻的地址可以填入到目标代码中,18,静态存储分配策略对源语言的限制,数据对象的大小和它们在内存中的位置必须在编译时都能够确定 不允许过程递归调用 因为使用静态存储分配,一个过程里声明的局部数据在该过程的所有活动中都结合到同一个地址。 不能建立动态数据结构 因为没有在运行时进行存储分配的机制。,19,静态存储分配策略的实现,编译器处理声明语句时,每遇到一个变量名就创建一个符号表条目,填入相应的属性,包括目标地址。 每个变量所需空间的大小由其类型确定,并且在编译时刻是已知的。 根据名字出现的先后顺序,连续分配空间,name type address . length,N1 0 n1,N2 n1 n2,N3 n1+n2 n3,. . .,代码区,数据区,N1,N2,.,20,PROGRAM CNSUME CHARACTER *50 BUF INTEGER NEXT CHARACTER C, PRDUCE DATA NEXT /1/, BUF / / 6 C=PRDUCE() BUF (NEXT:NEXT)=C NEXT=NEXT+1 IF (C .NE. ) GOTO 6 WRITE (*, (A) BUF END,Fortran程序举例,CHARACTER FUNCTION PRDUCE() CHARACTER *80 BUFFER INTEGER NEXT SAVE BUFFER,NEXT DATA NEXT /81/ IF (NEXT .GT. 80) THEN READ (*, (A) BUFFER NEXT=1 END IF PRDUCE=BUFFER (NEXT:NEXT) NEXT=NEXT+1 END,21,存储空间分配,静态数据区,代码区,22,二、栈式存储分配,存储空间被组织成栈 存储管理 活动开始时,与活动相应的活动记录入栈,局部变量的存储空间分配在该活动记录中。同一过程中声明的名字在不同的活动中被结合到不同的存储空间。 活动结束时,活动记录出栈,分配给局部名字的存储空间被释放。名字的值将丢失,不可再用。,23,program sort(input, output); var a: array0.10 of integer; x: integer; procedure readarray; var i: integer; begin for i:=1 to 9 do read(ai) end; prcedure exchange(i, j: integer); begin x:=ai; ai:=aj; aj:=x end;,procedure quicksort(m, n: integer); var k, v: integer; function partition(y, z: integer): integer; var i, j: integer; begin a ; v ; exchange(i, j); end; begin if (nm) then begin i:=partition(m, n); quicksort(m,i-1); quicksort(i+1, n) end end quicksort; begin a0:=-999; a10=999; readarray; quicksort(1, 9) end sort.,对读入的数据进行排序的PASCAL程序,24,控制栈的变化举例,S,r,q(1,9),p(1,9) =4,q(1,3),p(1,3) =1,e(1,9),e(1,3),q(1,0),q(2,3),k,入栈? 出栈?,25,调用序列,除局部数据外,活动记录中还有实现过程调用和返回的控制信息 活动记录的入栈,实现了控制从调用过程到被调用过程的转移 控制的转移由一段代码(即调用序列)
网站客服QQ:2055934822
金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号