编译原理-刘善梅-第9章 运行时存储空间组织4
编译原理运行时存储空间的组织和管理课件

变量和数据的存储
• 静态存储:在编译时分配固定大小的内存空间。 • 动态存储:在运行时动态地分配和释放内存空间。 • 数据对齐:为了提高访问效率,对变量在内存中的位置进行调整。 • 在程序中,变量和数据的存储方式通常分为静态存储和动态存储两种。静态存
储是指在编译时就为变量分配固定大小的内存空间,这种方式适用于在程序执 行期间大小不变的变量。而动态存储是在运行时动态地为变量分配和释放内存 空间,它适用于大小在运行时才能确定或者在程序执行过程中会发生变化的数 据结构。为了提高内存访问效率,编译器通常还会进行数据对齐操作,即调整 变量在内存中的位置,使其按照特定的字节边界对齐,这样可以减少CPU访 问内存的次数,提高程序的执行速度。
04 数据段和代码段 的管理
数据段的组织和管理
静态存储分配:在编译时确定变量的 存储空间需求,并为其分配固定的存 储空间。这种分配方式适用于全局变 量和静态变量,其存储空间通常位于 数据段中。
动态存储分配:在运行时根据程序的 需要动态地分配存储空间。这种方式 适用于局部变量和临时变量,其存储 空间通常位于栈或堆中。动态存储分 配能够更有效地利用存储空间,并根 据需要动态调整。
03 堆区和栈区的管 理
堆区的组织和管理
动态内存分配
内存碎片问题
堆区是程序中用于动态内存分配的区 域,使用堆区可以实现在运行时根据 需要动态地分配和释放内存空间。在 堆区中,内存块的大小和数量是灵活 的,可以根据程序的需求进行调整。 常用的动态内存分配函数包括 malloc()和new()。
由于堆区的动态分配特性,频繁地分 配和释放内存块可能会导致内存碎片 问题。内存碎片指的是堆区中无法被 有效利用的小块内存空间。为了解决 这个问题,可以采用内存池技术,预 先分配一大块内存空间,并将其划分 为多个小块,每次需要分配内存时, 从内存池中获取一块合适的内存块。
编译原理chapter9 运行时存储空间组织

chapter9
运行时存储空间组织
Chapter9 运行时存储空间组织
编译原理
chapter9
运行时存储空间组织
9.1 目标程序运行时的活动 9.2 运行时存储器的划分 9.3 简单的栈式存储分配 9.4 嵌套过程语言的栈式实现 9.5 堆式动态存储分配
编译原理
chapter9
运行时存储空间组织
编译原理
chapter9
运行时存储空间组织
1. 带有静态链的活动记录 带有静态链 静态链的活动记录 静态链:它指向直接外层过程的活动记录的起始位置, 静态链:它指向直接外层过程的活动记录的起始位置, 直接外层过程的活动记录的起始位置 用于访问各外层的变量(非局部变量)。 用于访问各外层的变量(非局部变量)。
动态链:指向调用本过程的最新活动 ④. 动态链:指向调用本过程的最新活动 返回地址 记录的起始地址; 记录的起始地址; 动态链 每个活动记录的大小在编译时可以确定 SP ( 除动态数据 ),因此以 为变址器可方便的访问各个数据 ,因此以SP为变址器可方便的访问各个数据
编译原理
chapter9
运行时存储空间组织
top
u=15 v=10 形式单元 参数个数 gcd(15,10)
sp top sp
2 返回地址 老sp
x=15 y=10
main() 全局 /静态区 静态区
编译原理
chapter9
运行时存储空间组织
program p; 9.4 嵌套过程语言的栈式实现 var a,x:integer; 语言为例, 以Pascal语言为例Q(b:integer); 语言为例 由于允许嵌套定义过程, procedure ,由于允许嵌套定义过程,则会 var i:integer; 出现“非局部名字的访问”问题。 出现“非局部名字的访问”问题。因此简单的栈式存储分 procedure R(u:integer;var v:integer); 配不适用。 配不适用。 var c,d:integer; begin if u=1 then R(u+1,v) 活动记录中可配有静态链和嵌套层次表两种方式来实现。 静态链和嵌套层次表43;c)*(b-d); 两种方式来实现。 end {R} begin …. R(1,x); ……. end {Q} procedure S; var c,i:integer; begin a=1;Q(c); …….end {S} begin a=0;S;…… end
编译原理教案运行时存储空间经济组织课件

内存生长方向
堆的生长方向向上,即地址由低到高;栈的生长方向向下 ,即地址由高到低。
效率
由于堆需要手动管理,其操作相对复杂,效率较低;栈由 编译器自动管理,操作简便,效率高。
应用场景
堆适用于需要灵活、动态分配内存的场景,如数据结构、 算法等;栈适用于函数调用、局部变量等短暂、固定大小 的内存需求场景。
以上是关于编译原理中运行时存储空间经济组织的课件内容。通过深入了解数据的存储布局 、动态内存分配与管理以及运行时堆的管理策略,可以更好地优化程序的内存使用,提升程 序性能,并减少潜在的内存相关错误。
04
程序执行过程中的内存变化
函数调用与返回时的内存变化
栈帧生成
参数传递
当函数被调用时,会为该函数创建一个栈 帧,用于存储该函数的局部变量、返回地 址以及临时数据。
运行时堆的管理策略
堆的分配策略:堆区通常采用链表、树等数据结构来管理空闲内存块。常见的堆分配策略包 括首次适配(first-fit)、最佳适配(best-fit)和最坏适配(worst-fit)等。
垃圾回收:为了减轻程序员手动管理内存的负担,一些编程语言(如Java和Python)采用 了自动垃圾回收机制。垃圾回收器会定期检测程序中不再被引用的对象,并自动回收其占用 的内存空间。
课程目标和期望
01
02
03
04
知识掌握
深入理解编译原理中各个阶段 ,及它们如何影响存储空间经
济。
能力培养
能够设计和实现具有高效存储 空间管理的编译器。
思维拓展
通过编译原理的学习,培养计 算思维和问题解决能力。
实用技能
掌握一些实用的编译优化技术 和存储空间管理方法。
02
运行时存储空间基础概念
编译原理运行时存储空间经济组织

《编译原理运行时存储空间经济组织ppt》2023-10-26CATALOGUE目录•编译原理概述•运行时存储空间概述•存储空间的经济组织•存储空间的扩展与维护•编译原理与存储空间的结合应用•总结与展望01编译原理概述1 2 3编译原理是研究如何将高级语言程序翻译成低级语言程序的一门科学。
编译原理定义编译原理关注如何将程序翻译成更低级的语言,以优化程序的运行效率和减小存储空间的使用。
编译原理的关注点编译原理包括词法分析、语法分析、语义分析、优化和代码生成等多个环节。
编译原理的基本组成语法分析根据语言的语法规则,将单词或符号组成语法结构。
词法分析将源程序分解成一个个的单词或符号。
语义分析对语法结构进行语义检查,确保其符合语言的语义规则。
代码生成将优化后的程序翻译成目标机器语言。
优化对已通过语义检查的程序进行优化,以提高程序的运行效率。
编译原理的应用编译器设计编译原理是设计编译器的基础,编译器是实现程序从高级语言到低级语言转换的关键工具。
要点一要点二程序优化利用编译原理中的优化技术,可以提高程序的运行效率,减少存储空间的使用。
语言设计编译原理在语言设计中也有重要的应用,它可以帮助设计者更好地理解语言的语法和语义规则。
要点三02运行时存储空间概述运行时存储空间的概念运行时存储空间指在程序运行过程中,用于存储程序中的变量、函数、类等数据和信息的空间。
运行时存储空间的分类根据存储空间的位置,可以分为内存空间和外存空间。
内存空间包括RAM、Cache等,外存空间包括硬盘、固态硬盘等。
在程序编译时,根据程序中使用的变量、函数、类等信息,分配相应的内存空间。
这种方式适用于程序中数据和函数的使用情况在编译时已知的情况。
在程序运行时,根据实际需要动态地分配内存空间。
这种方式适用于程序中数据和函数的使用情况在编译时无法确定的情况。
静态分配动态分配内存管理单元(MMU)用于管理内存空间的分配和释放。
MMU根据程序的请求,分配相应的内存空间,并在程序结束时释放相应的内存空间。
编译原理运行时存储空间组织陈火旺版.ppt

TOP→ 临时单元 内情向量 局部变量 形式单元 静态链 动态链
SP→ 返回地址
局部数据区 连接数据
三.存储分配策略
静态存储分配 在编译时对所有数据对象分配固定的存储单元 (FORTRAN) 且在运行时始终保持不变 栈式 在运行时把存储器作为一个栈进行管理,运行 时每当调用一个过程,它所需空间就动态分配于 栈顶,一旦退出,所占空间予以释放(C,Pascal)
故返回P:=x+y ,即Z=4.
例2.(上海交通大学)假定下列程序在语法上是正确的。 Program text (input,output); Var i,j:integer procedure cal (x,y:integer); begin y:=y**2; x:=x-y; y:=y-x; end ; {cal} begin {main} i:=2 ; j:=3; cal(i, j); writeln(j:1) end {main} 采用哪种参数传递方式使上述程序打印16,采用哪种 方式使程序结果为3 传地址、传名 传值
例1.(清华大学 考研试题) 在下面的函数P中,参数x是通过地址传递的,参数y通过 值传递
FUNCTION P(VAR x:integer ; y:integer) : integer; BEGIN K:=3; L:=5; P:=x+y
END; 若P由下列程序调用
K:=1;
L:=1;
Z:=P(K,L) 则问Z的值是什么,这两种参数传递机制如何实现?
解:当传值时,在调用段对参数进行的修改在主程序 段中不对参数实际值造成影响,而传地址时,在 调用段对参数的修改就实际改变了参数值 x传地址 y传值 Z:=P(K,L) K地址传到调用段。K:=3即x:=3 y只是L的值,过程体中L:=5不改变y的值 故此时 x=3,y仍为1。 所以P:=x+y,即为P:=3+1=4。
编译原理目标程序运行时的存储组织

编译原理目标程序运行时的存储组织引言在编译原理中,目标程序是指通过编译器将高级源代码转换为机器可执行的程序。
在目标程序运行时,需要一定的存储空间来存储程序的指令和数据。
本文将介绍编译原理中目标程序运行时的存储组织的基本概念和原理。
程序的内存模型目标程序在运行时的存储组织是通过内存模型来描述的。
内存模型定义了目标程序在内存中的存储方式和访问机制。
常见的内存模型有栈式模型、堆式模型和段式模型等。
栈式模型栈式模型将程序的内存划分为栈和堆两部分。
栈用于存储程序的局部变量、函数调用和返回地址等信息,而堆用于动态存储分配,如动态创建的对象以及通过malloc等函数分配的内存。
栈式模型的存储空间是连续分配的,栈的大小是固定的,而堆的大小可以根据需要进行动态调整。
堆式模型堆式模型将程序的内存划分为堆和栈两部分。
堆是动态分配的内存空间,用于存储程序运行时动态创建的对象和变量。
栈则用于存储函数调用的临时变量、函数参数和返回地址等信息。
堆式模型的存储空间可以动态调整,但需要手动管理内存的分配和释放,以避免内存泄漏和内存碎片的产生。
段式模型段式模型将程序的内存划分为若干个段,每个段用于存储特定类型的数据。
常见的段包括代码段、数据段、堆段和栈段等。
代码段用于存储程序的指令,数据段用于存储常量、全局变量和静态变量等数据,堆段和栈段与堆式模型和栈式模型类似。
段式模型可以更灵活地管理不同类型的数据,提高了内存的利用率。
存储器分配在目标程序运行时,编译器负责将程序的指令和数据分配到合适的存储器中。
存储器分配的主要目标是提高程序的执行效率和优化存储空间的利用率。
静态存储器分配静态存储器分配是在编译时确定存储器的分配方式。
静态存储器分配将程序的指令和数据分配到固定的内存地址上,程序运行时不会改变存储器分配。
静态存储器分配适用于程序结构稳定、数据量较小的场景,但难以适应动态创建和销毁对象的情况。
栈式存储器分配栈式存储器分配将程序的局部变量、函数调用和返回地址等信息存储在栈中。
编译原理目标程序运行时的组织

编译原理目标程序运行时的组织简介在编译原理中,目标程序是由程序设计语言的源代码通过编译器转换而成的可执行文件。
目标程序的运行是通过操作系统的支持以及相关的硬件来完成的。
在目标程序运行时,需要对内存的组织进行有效的管理,以保证程序能够正确地执行。
程序的存储结构目标程序在运行时的组织首先涉及到程序的存储结构。
一般来说,目标程序在存储器中被组织为多个段或者区块。
这些段或者区块包括代码段、数据段、堆栈段等。
每个段都有不同的权限,比如代码段通常是只读的,数据段和堆栈段都是读写的。
代码段代码段是存储目标程序的机器指令的区域。
代码段在目标程序运行时是只读的,因为在运行时不能更改源代码。
代码段通常是按照顺序组织的,每条指令都有一个地址。
当程序执行时,计算机会从代码段中读取指令并逐条执行。
数据段数据段是存储目标程序的静态数据、全局变量以及常量的区域。
数据段在目标程序运行时是读写的,因为数据段中的数据可能会发生变化。
数据段通常是按照数据的类型和大小进行组织的,每个数据都有一个地址。
堆栈段堆栈段是存储目标程序的局部变量、函数的参数和返回值等临时数据的区域。
堆栈段在目标程序运行时是读写的,因为堆栈中的数据会被不断压入和弹出。
堆栈段通过栈的数据结构进行组织,数据的压入和弹出都是通过栈指针来实现的。
内存管理目标程序在运行时需要使用内存进行存储和计算。
内存管理是指程序如何分配、使用和释放内存资源的过程。
在目标程序运行时,操作系统负责管理内存的分配和释放,并对内存进行保护,以防止程序的错误操作导致系统崩溃或安全风险。
内存管理的主要任务包括内存分配、内存回收和内存保护。
内存分配是指为程序分配所需的内存空间。
常见的内存分配方式有静态分配和动态分配。
静态分配是在程序加载到内存时预先分配一定的内存空间,而动态分配是根据程序的需要,在运行时临时分配内存空间。
内存回收是指当某个内存空间不再被程序使用时,将其释放回系统。
常见的内存回收方式有手动回收和自动回收。
编译原理运行时存储空间组织

主程序P
TOP 4
3
2
1
SP 0
x a 0 返回地址
0
主程序P过程 S
TOP 10
9 8 7 6
SP 5
4 3 2 1 0
动态链
i c 0(形参个数) 0 返回地址
0 x a 0 返回地址
0
?第N层过程调用
第 N+1层过程,如何 确定被调用过程(第 N+1层)过程的静态链?
A:调用过程(第N层
每个过程的活动记录内容如图:
TOP
2 1 SP 0
临时单元 内情向量 局部变量 形式单元 参数个数 返回地址
老SP
对任何局部变量X的 引用可表示为变址访 问:
dx[SP] dx: 变量X相对于活 动记录起点的地址, 在编译时可确定。
9.5 嵌套过程语言的栈式实现
假定语言不仅允许过程的递归调用(和可变 数组),而且允许过程定义的嵌套,如 PASCAL,PL语言。
临时单元 内情向量 局部变量 形式单元
静态链 动态链 返回地址
连接数据
➢返回地址 ➢动态链:指向调用该 过程前的最新活动记 录地址的指针。
➢静态链:指向静态直 接外层最新活动记录 地址的指针,用来访 问非局部数据。
每个过程的活动记录内容
TOP
2 1 SP 0
临时单元 内情向量 局部变量 形式单元
静态链 动态链 返回地址
procedure quicksort(m, n:integer); var i:integer; begin if (n>m) then begin i:=partition(m, n ); quicksort(m, i-1 ); quicksort(i+1, n ) end; end;
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
PASCAL的变var m:integer; var n: integer); var i:integer; begin
i:=m; m:=n; n:=i; end
swap(a,b) 把a,b的地址送到已知单元j1和j2中 m:=j1; n:=j2; i:=m↑; m↑:= n↑; n↑:=i;
program sort procedure readarray function partition procedure quicksort
(12) procedure quicksort(m, n:integer);
(13) var i:integer;
(14) begin
(15) if (n>m) then begin
传值、传址、得结果、传名
第九章 运行时存储空间组织
目标程序运行时的活动 运行时存储器的划分 静态存储管理 一个简单栈式存储分配 嵌套过程语言的栈式实现
编译程序组织存储空间须考虑的问题:
过程是否允许递归? 当控制从一个过程的活动返回时,对局部名
z:=x+y; end;
过程调用
add(a,b,c);
参数传递方式
传地址 得结果 传值 传名
参数传递方式
一. 传地址
把实在参数的地址传递给相应的形式参数 方法:
调用段预先把实在参数的地址传递到被调用段 可以拿到的地方;
程序控制转入被调用段之后,被调用段首先把 实在参数的地址抄进自己相应的形式单元中;
过程调用的作用相当于把被调用段的过程 体抄到调用出现的地方,但把其中任一出 现的形式参数都替换成相应的实参。
方法:
在进入被调用段之前不对实在参数预先进行计 值,而是让过程体中每当使用到相应的形式参 数时才逐次对它实行计值(或计算地址)。因 此,通常把实在参数处理成一个子程序(称为 参数子程序),每当过程体中使用到相应的形 式参数时就调用这个子程序。
write(A); END
例:
…
procedure P(w,x,y,z);
begin
y := y*w;
z := z+x;
end begin
a := 5; b := 3; P(a+b,a-b,a,a);
传值: 5 传地址: 42 得结果: 7 传名: 77
write(a);
end
传名
…
procedure P(w,x,y,z);
(4) var i: integer;
(5) begin
(6) for i:=1 to 9 do read(a[i])
(7) end;
(8) function partition(y, z:integer):integer;
(9) var i:integer; (10) begin ...... (11) end;
编译原理
第九章 运行时存储空间组织
第九章 运行时存储空间组织
目标程序运行时的活动 运行时存储器的划分 静态存储管理 一个简单栈式存储分配 嵌套过程语言的栈式实现
第九章 运行时存储空间组织
9.1 目标程序运行时的活动
以Pascal为例,假定程序由若干个过程组 成
过程(procedure)定义 一个过程的活动指的是该过程的一次执行
begin
y := y*w;
BEGIN
z := z+x;
a := 5;
end
b := 3
begin a := 5; b := 3;
a:= a*(a+b) ; a:= a+(a-b) ;
write(a);
P(a+b,a-b,a,a); END
write(a);
end
小结
目标程序运行时的活动 参数传递
参数传递方式
二.得结果 传地址的一种变形 方法:
每个形参对应两个形式单元,第一个形式单元 存放实参地址,第二个单元存放实参的值。
在过程体中对形式参数的任何引用或赋值都看 作对它的第二个单元的直接访问。
过程完成返回前把第二个单元的内容存放到第 一个单元所指的实参单元中。
有些Fortran采用这种方式;
参数传递方式
三.传值 把实在参数的值传递给相应的形式参数 方法:
调用段预先把实在参数的的值计算出来并放 在被调用段可以拿到的地方;
被调用段开始工作时,首先把实参的值抄入 形式参数相应的单元;
被调用段中,象引用局部数据一样引用形式 单元。
PASCAL的值参数
参数传递方式
四.传名
(21) begin
(22) a[0]:=-9999; a[10]:=9999;
(23) readarray;
(24) quicksort(1, 9 )
(25) end.
参数传递
过程是模块程序设计的主要手段,同时也 是节省程序代码和扩充语言的主要途径。
过程定义:
procedure add(x,y:integer; var z:integer) begin
P…ROGRAM EX var A:integer; P…ROCEDURE P(B:integer) var A:integer; BEGIN A:=0; B:=B+1; A:=A+B; END;
BEGIN A:=2; P(A); write(A);
END
传名举例
BEGIN A :=2;
TA:=0; A:= A +1; TA:=TA+ A;
过程P一个活动的生存期,指的是从执行该过 程体第一步操作到最后一步操作之间的操作序, 包括执行P时调用其它过程花费的时间
过程可以是递归的
(1) program sort(input, output)
(2) var a: array[0..10] of integer;
(3) procedure readarray;
(16) i:=partition(m, n );
(17) (18) (19)
quicksort(m, i-1 ); quicksort(i+1, n ) end;
program sort procedure readarray function partition
(20) end;
procedure quicksort