72
第第第第 第第第第第第第第第第 第第第第第第第 第第第第第第第第第第第 第第第第第第第 第第第第第第 第第第第第 第第第第第第 一:、

第十三章 运行时存储空间的组织

Embed Size (px)

DESCRIPTION

第十三章 运行时存储空间的组织. 第一节 变量及存储分配 程序投入运行的必要条件: 一组可运行的代码 一个运行环境:分配空间、提供运行信息. 一 . 程序的存储空间 1. 代码空间 : 线性存放着目标指令序列 在 GAM 中 , 当前执行的指令位置由指令指针 ip 指示。 2. 数据空间 (1) 内容 : 变量、常数、控制和管理信息、描述符等. (2) 静态分配 : 在运行前就可确定数据空间的大小 , 在编译时刻就能进行的存储分配 (3) 动态分配 : 运行时才能进行的存储分配 - PowerPoint PPT Presentation

Citation preview

Page 1: 第十三章 运行时存储空间的组织

第十三章 运行时存储空间的组织第一节 变量及存储分配

程序投入运行的必要条件: 一组可运行的代码 一个运行环境:分配空间、提供运行信息

Page 2: 第十三章 运行时存储空间的组织

一 . 程序的存储空间 1. 代码空间 : 线性存放着目标指令序列 在 GAM 中 , 当前执行的指令位置由指令指针 ip 指示。 2. 数据空间 (1) 内容 : 变量、常数、控制和管理信息、描述符等

Page 3: 第十三章 运行时存储空间的组织

(2) 静态分配 : 在运行前就可确定数据空间的大小 , 在编译时刻就能进行的存储分配 (3) 动态分配 : 运行时才能进行的存储分配 栈分配 : 因变量生存期的嵌套性 堆分配 : 因生存期的随机交叉特性

Page 4: 第十三章 运行时存储空间的组织

二 . 活动记录 一个程序单元的一次激活所需的信息管理是通过相应的活动记录来实施的。一个单元的每次激活,都应建立相应的活动记录,它是单元实例的一部分。

Page 5: 第十三章 运行时存储空间的组织

1. 活动记录的内容 (1) 返回地址 (2) 动态链和静态链 (3) 形式单元 (4) 局部变量或其描述符,以及临时变量

返回地址动态链静态链

变量存储区形式单元

Page 6: 第十三章 运行时存储空间的组织

2. 活动记录的特点 除了变量存储区外 , 其余部分存储长度编译时可以确定 , 则元素 i 的地址可用下式计算 D+offset(i)其中 , offset(i) 是 i 在活动记录中的位移 ; D是活动记录的首地址

Page 7: 第十三章 运行时存储空间的组织

三 . 变量的存储分配 1. 静态变量 : 不管在程序单元的哪一次活动中 , 均绑定于相同的存储位置 条件是 : 活动记录 , 变量的存储位置在编译时可以确定 2. 半静态变量 : 编译时确定相对位置 , 单元被激活后 , x 绑定于 D+offset(x) 条件是 : 语言允许递归调用

Page 8: 第十三章 运行时存储空间的组织

3. 半动态变量 : 动态数组 ; 编译时在活动记录中建立描述符例 : [1..m] int a; [1..n] int b; 4. 动态变量 : 动态分配。编译时在活动记录中为动态变量设置二个指针 , 一个指向该变量的描述符 , 另一个指向该变量的存储空间

Page 9: 第十三章 运行时存储空间的组织

四 . 存储分配模式 1. 静态分配 只允许静态变量 , 变量与存储区域的绑定关系在编译时便可建立 , 并完成存储分配。 不允许递归调用 , 不允许动态数组 , 不允许动态类型的数据对象 , 即不允许有非静态变量。如 : FORTRAN 语言。

Page 10: 第十三章 运行时存储空间的组织

2. 栈式分配 各单元之间的调用关系遵循“后进先出”模式 ; 活动记录的建立和撤消也满足“后进先出”模式 ; 用栈分配活动记录 ; 分配方法 : 当激活一个程序单元时 , 其活动记录就动态地分配于栈顶。

Page 11: 第十三章 运行时存储空间的组织

R 的活动记录

Q 的活动记录P 的活动记录

如: P 调用 Q , Q 调用 R

......

...

Page 12: 第十三章 运行时存储空间的组织

3. 堆分配 由于动态变量表示的数据对象 , 它的长度、个数都有可能在执行中改变 , 即在其生存期中动态改变 , 就不可能在栈上为这样的对象作分配。 出现下列情况时 , 必须用堆式分配 : (1) 单元活动结束后 , 局部变量的值还需保留 ; (2) 调用单元与被调用单元的生存期不满足嵌套关系 , 即出现交叉现象。

Page 13: 第十三章 运行时存储空间的组织

4. 存储空间的组织代码

静态数据栈

Page 14: 第十三章 运行时存储空间的组织

第二节 静态分配O. FORTRAN 语言的特点 1. 模块结构 一个主程序段和若干个 ( 可以是 0 个 )辅程序段组成 ; 辅程序段可以是子程序、函数段或数据块;各段可以独立编译。 2. 说明语句无严格语序 , 且具有显式说明和隐式说明。

Page 15: 第十三章 运行时存储空间的组织

INTEGER A, BDIMENSION X, YDIMENSION B(10)REAL X(20)INTEGER Y(10,20)COMMOM A, XEQUIVALENCE (I, B(4)), (X(2), Z)

例 :

Page 16: 第十三章 运行时存储空间的组织

3. 公用 (COMMON) 和等价 (EQUIVALENCE) 语句建立了数据空间的同一性。

4. 不允许过程的递归性 ; 每个数据名所需的存储空间大小都是常量 ; 所有数据名的性质是确定的。

Page 17: 第十三章 运行时存储空间的组织

一 . FORTRAN 程序运行时的结构 由 FORTRAN 的特点知,每个单元的

活动记录及变量在运行前便可建立,其生存期延续到整个程序结束。

Page 18: 第十三章 运行时存储空间的组织

1. FORTRAN 程序编译过程(1) 编译时,变量约束于活动记录的常量位移,对变量的引用可用二元式(单元名,位移)表示;转换控制语句中对指令的引用也可翻译成二元式(单元名,指令在代码段中的位移)。

Page 19: 第十三章 运行时存储空间的组织

(2)连接时,须将程序所有单元连接起来,将代码段分配到代码区,活动记录分配到数据区。同时将编译时的二元式转换为地址。(3)装入时,将连接后的可重定位代码程序装入主存储器并定位,成为可直接执行的机器代码,并将 ip 指向程序第一条指令,使程序处于可执行状态。

Page 20: 第十三章 运行时存储空间的组织

2. FORTRAN 程序在 GAM 中的存储结构单元 1 代码段单元 2 代码段

单元 n 代码段

全局数据活动记录单元 1 活动记录单元 2 活动记录

单元 n 活动记录…

...

…...

ip

Page 21: 第十三章 运行时存储空间的组织

二 . 运行环境的转换约定: d [i, j] —— 单元 i 的活动记录中位移为 j 的存储单元内容 c [i, j] —— 单元 i 的代码段中位移为 j 的指令 D [ m ],C[m]——连接后的实际存储地址 & X —— X 的地址

Page 22: 第十三章 运行时存储空间的组织

1. GOTO X 语句 ip := & c [ i , j ]

其中 , c[i, j] 是编译后标号 X 对应的二元式

Page 23: 第十三章 运行时存储空间的组织

2. 过程调用语句 CALL P (1) 保存返回地址

d [P , 0 ] := ip + 2(2)转入 P ip := & c [ P , 0 ]连接后: D [m ] := ip + 2 ip := n其中 , m 为 P 的活动记录的首址 ;n 为 P 代码段首址

Page 24: 第十三章 运行时存储空间的组织

3. 返回语句 RETURN

取返回地址 ip := d [ P , 0 ]

连接后 ip := D [m ]

其中 m 是单元 P 的活动记录的首址

Page 25: 第十三章 运行时存储空间的组织

举例: INTEGER I , J /* 主程序 */ COMMON I CALL X GOTO 10

10 CONTINUE END

SUBROUTINE X /* 子程序 */ INTEGER K , J COMMON I K = 5 I = 6 J = I + K RETURN

END

Page 26: 第十三章 运行时存储空间的组织

D[3]:=ip+2ip:=5ip:=3noophaltD[4]:=5D[0]:=6D[5]:=D[0]+D[4]ip:=D[3]halt

0

1

23 4

5 6 7 8 9

代码存储器

Page 27: 第十三章 运行时存储空间的组织

01

234

5

common

main

X

I

返回地址J返回地址KJ

ip=0

数据存储器

Page 28: 第十三章 运行时存储空间的组织

01

234

5

common

main

X

I

返回地址J返回地址KJ

ip=5

数据存储器

2

Page 29: 第十三章 运行时存储空间的组织

01

234

5

common

main

X

I

返回地址J返回地址KJ

ip=7

数据存储器

6

25

Page 30: 第十三章 运行时存储空间的组织

01

234

5

common

main

X

I

返回地址J返回地址KJ

ip=2

数据存储器

6

25

11

Page 31: 第十三章 运行时存储空间的组织

第三节 栈式分配 语言特点:允许递归,允许动态数组,

允许过程嵌套定义

Page 32: 第十三章 运行时存储空间的组织

一 . 只含半静态变量的栈式分配1. 特点: 仅允许递归调用 变量及活动记录长度可静态确定 一个单元可多次激活而有多个实例,每个活动记录是在单元每次激活时动态建立并与代码段建立绑定关系的

Page 33: 第十三章 运行时存储空间的组织

2. 处理方法(1) 设置当前栈指针 current ,表示当前活动记录的开始位置(2) 指针 free 表示数据存储器下一个可用单元(3) 变量绑定于它在活动记录中的常数位移 i, 变量通过 current 变址访问(4)A 调用 B 时,在 A 活动记录的栈顶之上建立起绑定于 B 的当前实例的活动记录(5)从 B 返回时,释放其活动记录

Page 34: 第十三章 运行时存储空间的组织

3. 动态连接和动态链 动态连接: A 调用 B 时, B 的活动记录中保存的 A 的活动记录地址 动态链:由动态连接组成的一个调用链

Page 35: 第十三章 运行时存储空间的组织

A

E

F

G

F

A call E; E call F; F call G; G call F;

......

......

...

Page 36: 第十三章 运行时存储空间的组织

4. CALL P 的处理(1) 保存返回地址 D [ free ] := ip + 5(2) 保存主调过程的 current D [free + 1] := current(3) 建立 P 的 current current := free(4) 调整 free free := free + L(5)转子

ip := P 的代码段首地址

Page 37: 第十三章 运行时存储空间的组织

返回地址动态连接

返回地址动态连接

A 的活动记录

即将建立的P 的活动记录

current

free

过程 A 中调用了 P

Page 38: 第十三章 运行时存储空间的组织

返回地址动态链

返回地址动态链

A 的活动记录

P 的活动记录current

free

进入过程 P 以后

Page 39: 第十三章 运行时存储空间的组织

5. RETURN 语句的处理(1)恢复 free free := current(2)恢复主调过程的 current current := D[current + 1](3) 返回

ip := D [free]

Page 40: 第十三章 运行时存储空间的组织

二 . 半动态变量的栈式分配 1. 活动记录内容 返回地址 动态链 静态链 保护区 参数单元 局部变量 临时变量 数组存储区其中,局部变量中包括数组的描述符

Page 41: 第十三章 运行时存储空间的组织

2. 动态数组空间的分配(1) 编译时,分配内情向量表区,并产生在运行时动态建立内情向量和分配数组空间的指令 ;(2) 一个单元激活后(进入该单元),遇到动态数组说明时,调用上述指令(填内情向量,分配数组空间),并调整 free := free + L 。

Page 42: 第十三章 运行时存储空间的组织

三 . 动态变量的存储分配 在堆上进行存储分配

Page 43: 第十三章 运行时存储空间的组织

四 . 非局部环境 非局部环境的引用必须考虑变量的作用域 1. 静态作用域规则——最近嵌套规则 (1) 嵌套的层次 最外层单元为 0层,若 P 是 Q 的直接外层,则 Q 的层次 = P 的层次 + 1

Page 44: 第十三章 运行时存储空间的组织

unit A;y: int;

unit B;

end B;

y: int;

unit C;

end D;

end C;…...

unit D;

……

…...

Page 45: 第十三章 运行时存储空间的组织

end E;

z: int;unit F;

end G;

unit G;x,y: int;…...

……

…...

unit E;

z:=x+y;

end F;

……

…...end A;

A

B

C

D

E

F G

x: int;

Page 46: 第十三章 运行时存储空间的组织

(2)最近嵌套规则 变量的作用域是指可访问该变量的程序范围 (I) 变量 x 在单元 U1 中被说明,则 x 的作用域局部于 U1 ,或称 x 在 U1 中是可见的 ; (II) 变量 x 在 U1 中没有被说明,则 x的作用域是包围 U1 的说明了 x 的最小外层单元。

Page 47: 第十三章 运行时存储空间的组织

2. 动态作用域规则 这是一种最近活动规则,对非局部变量,引用的应是最近外层中说明的。 动态作用域的最近外层指的是动态调用外层,如 A-E-F-G-F 的调用序列:当前 F 的调用外层为 G 。

Page 48: 第十三章 运行时存储空间的组织

五 . 对非局部环境的引用 1. 静态作用域规则 (1) 静态连接和静态链 静态连接:指向嵌套直接外层的最新活动记录的指针,它处于活动记录位移为 8的存储单元中。 静态链:各嵌套程序单元的活动记录中,静态连接的序列构成一个静态链。

Page 49: 第十三章 运行时存储空间的组织

(2) 非局部变量 x 的地址的求法 假设单元 p 中引用了单元 t 中的变量

x ,且 p ,t 的深度分别为 np, nt 。 设 d = np – nt ,将 x约束于( d , offse

t) ,问题的关键是找 t 的最新活动记录 Dt,而 Dt+ offset 即为 x 的地址。

Page 50: 第十三章 运行时存储空间的组织

np – nt = 0: x 为 p 中的局部变量 Dt = current np – nt = 1: t 是 p 的直接外层 Dt = D[current + 2] np – nt = 2: t 是 p 的再外层 Dt = D[D[current + 2] + 2] np – nt = 3: t 是 p 的再外层的外层 Dt = D[D[D[current + 2] + 2] + 2]

Page 51: 第十三章 运行时存储空间的组织

令 np – nt = d , 则 f(d) = if d = 0 then current else D[f(d-1)+2]f(d) 表示沿 p 的静态链在栈中向下搜索 d步。

Page 52: 第十三章 运行时存储空间的组织

(3) 静态连接的确定 单元 A 调用单元 B 的几种情形 :

(I)nA-nB=0 (II)nA-nB=-1 (III)nA-nB=1 (IV)nA-nB>1

B0B0 B0 B0B

A

call B

AB

call B

BA

call B

B

call B

A

PP1

Page 53: 第十三章 运行时存储空间的组织

(I)nA - nB = 0, B 的静态连接= f (1)

(II)nA - nB = -1, B 的静态连接= f (0 )

(III)nA - nB = 1, B 的静态连接= f (2)

(IV)nA - nB = d, B 的静态连接= f (d + 1)

Page 54: 第十三章 运行时存储空间的组织

(4) 调用语句 call B 的处理 D[free] := ip + 6 D[free + 1] := current D[free + 2] := f(d + 1) current := free free := free + L ip := B 的代码段首址

Page 55: 第十三章 运行时存储空间的组织

2. 动态作用域规则 此时,静态连接是一指针,指向动

态调用直接外层的活动记录,其实与动态连接一致。

Page 56: 第十三章 运行时存储空间的组织

第四节 堆分配一 . 进行堆分配的几种情形 1. 动态变量的描述符和变量存储区均

分配在堆上 2. 二个程序单元的生存期相互交叉时 3. 允许动态申请内存时

Page 57: 第十三章 运行时存储空间的组织

二 . 存储空间的组织 1. 自由块处于 free 指向的一个链表中 2. 使用块的信息登记于使用块记录中,释放时被连接到 free 链中

Page 58: 第十三章 运行时存储空间的组织

三 . 存储分配的几种情形 设自由块总长度为 N ,申请长度为 n 1. 有大于或等于 n 的自由块,采用首次拟合法 2. 自由块的长度均小于 n ,且 N ≥ n,移动使用块 3. N < n,回收无用单元

Page 59: 第十三章 运行时存储空间的组织

第五节 参数传递先看例子 : procedure swap (a , b : integer); var temp : integer; begin temp := a; a := b; b := temp end; …… call swap(x, y); …...

形式参数

实在参数

Page 60: 第十三章 运行时存储空间的组织

几点说明 :

1. 程序单元间通信方式有非局部环境和参数传递

2. 参数,形参,实参 3. 参数传递的三种类型:数据参数传

递,过程参数传递,类型参数传递

Page 61: 第十三章 运行时存储空间的组织

一 . 数据参数传递 以调用 swap ( i , a[i] ) 为例,且调用前

i = 3 , a 的几个元素分别为 7 , 1 , 4 ,5 , 8

Page 62: 第十三章 运行时存储空间的组织

1. 引用调用(传地址) 将实参的地址传递给相应的形参 在单元中对形参的引用,实际上是对形

式单元中实参地址的间接引用

Page 63: 第十三章 运行时存储空间的组织

swap(i,a[i]); 相当于执行 : a:=i 的地址 ; b:=a[3] 的地址 ; temp:=a; (temp=3) a:=b; (i=4) b:=temp; (a[3]=temp=3)执行结果 : i=4, a[3]=3

Page 64: 第十三章 运行时存储空间的组织

2. 值调用 形参只起局部变量作用 (1)传值 : 实参的值形式单元 (2) 结果调用 : 形参的结果值实参单元 (3)传值得结果:实参的值形式单元 形参的结果值实参单元 实现技术:一个形参对应两个单元

Page 65: 第十三章 运行时存储空间的组织

对“传值得结果” swap(i,a[i]); 相当于执行 : a1:=i 的地址 ; a2:=3; b1:=a[3] 的地址 ; b2:=4; temp:=a2; (temp=a2=3) a2:=b2; (a2=b2=4) b2:=temp; (b2=temp=3) a1:=a2; (i=a2=4) b1:=b2; (a[3]=b2=3)执行结果 : i=4, a[3]=3

Page 66: 第十三章 运行时存储空间的组织

3. 名调用 用实参原样替换形参的出现 若被调用单元中的局部名与调用处的名发生冲突,则对局部名重新命名 把实参用括号括起来 实现技术:把实参处理成一个子程序( thun

k, 称为参数子程序),对形参的每次引用就调用该子程序

Page 67: 第十三章 运行时存储空间的组织

swap(i,a[i]); 相当于执行 : temp:=i; (temp=i=3) i:=a[i]; (i=a[3]=4) a[i]:=temp; (a[i]=a[4]=temp=3)执行结果 : i=4, a[4]=3 (a[3] 不变 )

Page 68: 第十三章 运行时存储空间的组织

二 . 过程参数的传递 1. 调用形式

P……call Q(T)…...

Q(S)……call S…...

其中 , call S 实际上就是 call T, 因此需向形参 S传递 T 的代码首址以及 T 的引用环境

Page 69: 第十三章 运行时存储空间的组织

PT

call Q(T)

T TP

T

P

Q(S)

call S

Q(S)

call S

Q(S)

call S

Q(S)

call S

P

call Q(T)

call Q(T)

call Q(T)

2. 在静态作用域规则下 P 、 T 、 Q 之间的关系

Page 70: 第十三章 运行时存储空间的组织

(1) 可见, call S处 T 的非局部环境,应由单元 P 中 call Q(T)处 T 的非局部环境指出,即 f (d + 1) , d = nP -nT

(2)处理方法: 为 S 设置两个指针,一个是 T 的代码段首址,另一个是 T 的静态连接 执行 call S 时,将静态连接记入 T 的活动记录,执行 T 的代码

Page 71: 第十三章 运行时存储空间的组织

3. 在动态作用域规则下 call Q(T) 时只向 S传递 T 代码段首址 非局部环境由动态链给出,即 T 的动态外层总是 Q

Page 72: 第十三章 运行时存储空间的组织

第十三章习题13-2 、 13-4 、 7-4