编译原理 第10章 运行时的存储组织与分配
编译原理运行时存储空间的组织和管理课件

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

p3活动记录 存取链(静态链) 控制链(动态链)
p3活动记录 存取链(静态链) 控制链(动态链)
main活动记录
2、用Display表
Display表---嵌套层次显示表 当前激活过程的层次为K,它的Display表含有K+1个
单元,依次存放着现行层,直接外层…直至最外层的每 一过程的最新活动记录的基地址。 说明:1、由于过程的层数可以静态确定,因此每个过程 的Display表的体积在编译时即可以确定。
Q的 活动记录
P的 活动记录 主程序的 活动记录
DISPLAY表பைடு நூலகம்维护和建立
为便于组织存储区,将display作为活动记录的一 部分,其相对地址在编译时是完全可以确定的。
假设过程P1可调用P2,为了能在P2中建立P2的 display,在P1调用P2时设法把P1的display地址 作为连接数据之一(全局display地址)传送给P2, 因此连接数据包括: 老SP值(动态链) 返回地址 全局display地址
嵌套过程的栈式分配方案
分程序结构的存储分配方案
3、过程活动:一个过程的活动指的是该过程的一次执行。
4、活动记录:一个过程的一次执行所需要的信息使用一个连 续的存储区来管理,这个区(块)叫做一个活动记录。
活动记录一般包含:
(1)连接数据
返回地址—调用过程指令的下一条指令的地址。
动态链(控制链)—指向调用该过程活动记录地址的指针。用 于当调用返回时,将当前栈顶正确切换到调用者的活动记录
2、某过程p是在层次为i的过程q内定义的,并且q是 包围p的直接外层,那么p的过程层数为i+1。
例: program main(i,0);
编译原理第10章运行时的存储组织与分配

10.2 静态存储分配
在编译阶段由编译程序实现对存储空间的管理,为 源程序中的变量分配存储单元。
条件
➢在编译时能够确定变量在运行时的数据空间大小 ➢运行时不改变
编译原理第10章运行时的存储组织与 分配
FORTRAN程序的静态分配
编译原理第10章运行时的存储组织与 分配
动态存储分配 在目标程序运行阶段由目标程序实现对存
再见,see you again
2020/12/13
编译原理第10章运行时的存储组织与 分配
编译原理第10章运行时的存储组织与 分配
练习 下面程序的运行结果是什么?如果把第6行的(i+1)*fact( )改 成fact( )*(i+1)的话,则程序的运行结果是有什么变化?试分析 为什么会有这两种不同的结果。 int fact( ) { static int i=5; if(i==0) return 1; else { i--; return((i+1)*fact( )); //第6行 }} main( ) { printf("factor of 5!=%d\n",fact());}
为运行阶段实现存储奠定基础
编译原理第10章运行时的存储组织与 分配
教学内容
• 10.1 存储组织概述 • 10.2 静态存储分配 • 10.3 栈式动态存储分配 • 10.4 堆式动态存储分配
编译原理第10章运行时的存储组织与 分配
10.1 存储组织概述
运行时存储空间的划分
代码空间
目标代码空间 静态数据空间
储空间的组织与管理,为源程序中的变量分 配存储单元 特点 • 在目标程序运行时进行分配 • 编译时为运行阶段设计好存储组织形式,即为每个 数据项安排好它在数据区中的相对位置
编译原理目标程序运行时的存储组织

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

存储分配结构图
若主程序调用了过程Q,Q又调用了R,在R进入运行后的存 储结构如图(a)所示。
若主程序调用了过程Q,Q递归调用自己,在Q过程第二次进 入运行后的存储结构如图(b)所示。
若主程序先调用过程Q,然后主程序接着调用R,且Q过程不 调用Q和R,这时Q和R进入运行后的存储结构分别如图(c)和 (d)所示。
栈式存储分配的实现
过程的活动记录 简单的栈式动态分配实现 嵌套过程语言的栈式实现 分程序结构的存储管理
过程的活动记录
过程的活动记录是 一段连续的存储 区.用以存放过程 的一次执行所需要 的信息。
简单描述
简单描述
1.临时工作单元,比如计算表达式过程中需存放中间结果用 的临时值单元。
2.局部变量,一个过程的局部变量。 3 .保存机器状态,容纳该过程执行前关于机器状态信息,
另一部分则是用以管理过程活动的记录信息,即当一次过程调用出现 时,调用该过程的那个过程的活动即被中断,当前机器的状态信息, 诸如程序计数器(返回地址)、寄存器的值等等,也都必须保留在栈中。
当控制从调用返回时,便根据栈中记录的信息恢复机器状态, 使该过程的活动重新开始。
堆式动态存储分配
如果一个程序语言提供用户自由地申请数据空间和退还数据空间的机制 (如C++中的new,delete.Pascal的new,便是这种机制),或者不仅有过 程而且有进程的程序结构,即空间的使用未必服从“先申请后释放,后 申请先释放”的原则,那么栈式的动态分配方案就不适用了。这种情况 下通常使用一种称为堆式的动态存储分配方案。
第二,当从内层分程序向外转移时可能同时 要结束若干个分程序,恢复所要到达的那个 分程序的数据区需要顺序退出,浪费时间, 降低效率。
第十章目标程序运行时的存储组织PPT学习教案

Program main; 全局变量定义; Procedure R; … End(R); Procedure Q; …
若主程序调用Q,Q递归调用自己 ,在Q第二次进入运行后的存储结 构为:
代码区
主程序全局 数据区
Q的数据区
栈区
Q的数据区
End(Q); 主程序执行体
End.(main)
第22页/共24页
本章小结: ➢ 运行时内存的划分:代码区、静态数据区、
栈、堆; ➢ 存储分配策略:静态分配、堆分配、栈分
配 ➢ 参数传递的实现:如何进行实参与行参的
结合;如何在代码中实现对参数的正确存 取。
第23页/共24页
第9页/共24页
10.2.3 栈式动态存储分配
在数据空间中开辟一个栈区,每当调用一个过程时,它所需要的 数据空间就分配在栈顶,每当过程工作结束时就释放这部分空间。 空间的使用符合先借后还的原则。
特点:先借后还,管理简单,空间使用效率高 栈式动态存储分配适合于PASCAL、C等典型过程式语言。
第3页/共24页
10.1 运行时的存储空间结构
当程序运行时,存储区的内容包括: ➢ 目标代码
目标代码的大小在编译时可以静态确定,因 此可以把它放在静态确定的区域; ➢ 目标代码运行时的数据空间
❖ 数据空间包括:用户定义的各 种类型的数据对象;临时工作 :静 态数据区、第栈4页/共区24页和堆区
第5页/共24页
10.2 运行时的存储空间分配
影响分配策略的因素:
源语言的结构特点 源语言的数据类型 源语言中决定名字作用域的规则
编译器具体实现时,采用如下三种分配策略之一或三种的混合形 式。这三种方式是:
➢ 静态存储分配 ➢ 栈式动态存储分配 ➢ 堆式动态存储分配
编译原理课件第十章 目标程序运行时的存储组织
27
假如过程sort激活(调用)了过程quicksort,这时存储栈 激活(调用)了过程 假如过程 激活 , 中的情形如图10.12所示,其中在quicksort过程活动记录 所示,其中在 中的情形如图 所示 过程活动记录 中有一存储单元(用斜线描绘)用以记录过程 中有一存储单元(用斜线描绘)用以记录过程quicksort 可以引用sort中定义的变量 和x.也就是说,为了解决对 中定义的变量a和 .也就是说, 可以引用 中定义的变量 非局部变量的存取问题, 非局部变量的存取问题,必须设法跟踪每个外层过程的 最新活动记录的位置
30
因为PL/O的过程是无参过程,PL/O也无动态数组,所以 的过程是无参过程, 也无动态数组, 因为 的过程是无参过程 也无动态数组 它的过程活动记录的内容如图10.14所示: 所示: 它的过程活动记录的内容如图 所示
31
再回到图10.11例子,如果该程序的某次执行顺序为: 例子,如果该程序的某次执行顺序为: 再回到图 例子 sort quicksort quicksort partition
4
8.1 概述
从逻辑上看,代码生成前, 从逻辑上看,代码生成前,编译程序必 须进行目标程序运行环境的设计 运行环境的设计和 须进行目标程序运行环境的设计和数据 空间的分配 数据空间包括: 数据空间包括:用户定义的各种类型的 数据对象(变量和常量)所需的存储空 数据对象(变量和常量)所需的存储空 作为保留中间结果和传递参数的临 间,作为保留中间结果和传递参数的临 时工作单元,调用过程时所需的连接单 时工作单元,调用过程时所需的连接单 组织输入/输出所需的缓冲区. 输出所需的缓冲区 元,组织输入 输出所需的缓冲区.
12
(11) END
(12) CHARACTER FUNCTION PRDUCE() (13)CHARACTER * 80 BUFFER (14) (15) (16) (17) (18) (19) (20) INTEGER NEXT SAVE BUFFER, NEXT //PRDUCE函数体所拥有的静态量 函数体所拥有的静态量BUFFER, NEXT 函数体所拥有的静态量 DATA NEXT /81/ IF (NEXT .GT.80)THEN READ ( *,' (A)' )BUFFER NEXT=1 END IF
第10章目标程序运行时的存储组织
这里是传值)
第10章目标程序运行时的存储组织
(1)program reference(input,output);
(2)var a,b:integer;
(3)procedure swap({var} x,y:integer);
第10章目标程序运行时的存储组织
第10章目标程序运行时的存储组织
嵌套过程语言的栈式 分配方案
主要特点:
• (语言)一个过程可以引用包围它的任 一外层过程所定义的标识符(如变量, 数组或过程等)。
• (实现)一个过程可以引用它的任一外 层过程的最新活动记录中的某些数据。
第10章目标程序运行时的存储组织
第10章目标程序运行时的存储组织
(1)swap(x,y)
(2)int *x,*y;
(3){ int temp;
(4)
temp=*x; *x=*y; *y=temp;
(5)}
(6)main( )
(7){ int a=1,b=2;
(8) swap(&a,&b);
(9) printf(“a is now %d,b is now %d\n”,a,b);
(4) var temp:integer;
(5) begin
(6)
temp:=x;
(7)
x:=y;
(8)
y:=temp
(9) end;
(10)begin
(11) a:=1; b:=2;
(12) swap(a,b);
(13) writeln(‘a=‘,a);writeln(‘b=‘,b)
(14)end.
第10章 运行时的存储组织与分配
Fall 2010li weihuaDepartment of Computer Science & technology, Informationalschool, Yunnan University Compilers :Principles and Techniques Chapter 10 Run-Time Environments运行时存储组织的作用与任务 程序在存储器中的布局存储分配策略活动记录运行时存储组织的作用与任务−代码生成前如何安排目标机资源的使用−几个问题•数据表示如何在目标机中表示每个源语言类型的值•存储分配如何组织不同作用域变量的存储•过程实现如何实现过程/函数调用,参数传递代码生成前需要安排目标机资源的使用−代码生成的实质•建立如下关联/绑定(biding)源程序/中间代码的脚本↔运行时的脚本源程序/中间代码的名字↔运行时的存储−目标机资源的使用•内存/缓存:存放目标代码和数据(包括系统数据)•寄存器:存放控制信息和数据信息(常为中间信息)•操作系统资源数据表示−源程序中数据对象在内存或寄存器中的表示形式•源程序中数据对象的属性名字(name),类型(type),值(value),成员(component),偏移地址(offset),……•数据对象在内存或寄存器中的表示形式位、字节、字、字节序列、……•有些机器要求数据存放时要按某种方式对齐(align)如:要求所有数据存放的起始地址为能够被4整除数据表示举例−基本类型数据char 数据 1 byte integer 数据 4 bytesfloat 数据8 bytes boolean数据 1 bit / 1 byte 指针 4 bytes数组一块连续的存储区(按行/列存放)结构/记录所有域(field)存放在一块连续的存储区存储分配策略−静态分配•在编译期间为数据对象分配存储−动态分配•栈式分配将数据对象的运行时存储按照栈的方式来管理•堆式分配从数据段的堆空间分配和释放数据对象的运行时存储静态存储分配−在编译期间就可确定数据对象的大小•不宜处理递归过程或函数−某些语言中所有存储都是静态分配•如汇编语言,FORTRAN语言−多数语言只有部分存储进行静态分配•可静态分配的数据对象如大小固定且在程序执行期间可全程访问的全局变量,以及程序中的常量(literals,constants)•如C 语言中的static和extern变量栈式存储分配−用于有效实现层次嵌套的程序结构•如实现过程/函数,块层次结构−可以实现递归过程/函数•比较:静态分配不宜实现递归过程/函数−运行栈中的数据单元是活动记录(activation record)(专门介绍)堆式存储分配−从堆空间为数据对象分配/释放存储•灵活数据对象的存储分配和释放不限时间和次序−显式的分配或释放(explicit allocation / dealocation)•程序员负责应用程序的(堆)存储空间管理(借助于)编译器和运行时系统所提供的默认存储管理机制)−隐式的分配或释放(implicit allocation / dealocation)•(堆)存储空间的分配或释放不需要程序员负责,由编译器和运行时系统自动完成堆式存储分配−某些语言有显式的堆空间分配和释放命令•如:Pascal 中的new, depositC++ 中的new, delete•比较:C 语言没有堆空间管理机制,malloc()和free()是标准库中的函数,可以由library vendor提供−某些语言支持隐式的堆空间释放−不释放堆空间的方法z只分配空间,不释放空间,空间耗尽时停止z适合于堆数据对象多数为一旦分配,永久使用的情形z在虚存很大及无用数据对象不致带来很大零乱的情形也可采用运行时存储组织堆式存储分配−显式释放堆空间的方法•用户负责清空无用的数据空间(通过执行释放命令)•堆管理程序只维护可供分配命令使用的空闲空间•问题:可能导致灾难性的dangling pointer错误例:Pascal 代码片断C++ 代码片断var p,q: ^real; …new(p);q:=p; dispose(p);q^:=1.0;float * p,*q; …p=new float; q=p;delete p;*q:=1.0;堆式存储分配−堆空间的管理•分配算法面对多个可用的存储块,选择哪一个如:最佳适应算法(选择浪费最少的存储块)最先适应算法(选择最先找到的足够大的存储块)循环最先适应算法(起始点不同的最先适应算法)•碎片整理算法压缩合并小的存储块,使其更可用(可以分专门的话题讨论,超出本课程范围)(部分内容可参考数据结构和操作系统课程)活动记录−嵌套过程语言的栈式分配•主要问题解决对非局部量的引用(存取)•解决方案采用Display 寄存器表为活动记录增加静态链域活动记录−嵌套过程语言的栈式分配•采用Display 寄存器表Display 寄存器表(简称Display 表)记录各嵌套层当前过程的活动记录在运行栈上的起始位置(基地址)当前激活过程的层次为K(主程序的层次设为0),则对应的Display 表含有K+1 个单元,依次存放着现行层,直接外层…直至最外层的每一过程的最新活动记录的基地址嵌套作用域规则确保每一时刻Display 表内容的唯一性Display 表的大小(即最多嵌套的层数)取决于实现活动记录−嵌套过程语言的栈式分配•采用静态链(static link)Display 表的方法要用到多个寄存器,有时并不情愿这样做(寄存器资源很宝贵),一种可选的方法是采用静态链,只保留一个寄存器(即SP)指向当前AR所有活动记录都增加一个静态链(如在offset为0 处)的域,指向定义该过程的直接外过程(或主程序)运行时最新的活动记录在过程返回时当前AR 要被撤销,为回卷(unwind)到调用过程的AR(恢复SP),还需增加一个动态链过程调用与参数传递−参数传递方式•传值call-by-value传递的是实际参数的右值(r-value)•传地址call-by-reference(-address, -location)传递的是实际参数的左值(l-value)−注表达式的左值代表存储该表达式值的地址表达式的右值代表该表达式的值过程调用与参数传递−参数传递方式•实现call-by-value形式参数当作过程的局部变量处理,即在被调过程的活动记录中开辟了形参的存储空间,这些存储位置用以存放实参调用过程计算实参的值,将其放于对应的存储空间被调用过程执行时,就像使用局部变量一样使用这些形式单元过程调用与参数传递−参数传递方式•实现call-by-reference把实在参数的地址传递给相应的形参,即调用过程把一个指向实参的存储地址的指针传递给被调用过程相应的形参:若实在参数是一个名字,或具有左值的表达式,则传递左值若实在参数是无左值的表达式,则计算值,放入一存储单元,传此存储单元地址That’s all for today.Thank You。
编译原理课件第十章目标程序运行时的存储组织
PART 01
目标程序运行时的存储器 组织
存储器分类
主存储器
用于存储程序运行时所需的数 据和指令,具有较快的访问速
度。
辅助存储器
如硬盘、光盘等,用于存储大 量数据和程序,访问速度较慢 。
高速缓存存储器
位于CPU和主存储器之间,用 于缓存常用数据和指令,提高 访问速度。
寄存器
位于CPU内部,用于临时存储 数据和指令,访问速度最快。
01
数据段用于存储程序中定义的全 局变量、静态变量等数据。
03
数据段的大小在编译时确定,并 在程序运行时被加载到内存中。
02
数据段分为初始化数据段和未初 始化数据段,分别用于存储初始
化和未初始化的数据。
201 4
04
数据段的保护机制可以防止其他 程序或用户随意修改其中的数据。Fra bibliotek堆栈段
01
堆栈段用于存储函数调用的参数、局部变量以及函数调用的返回地址 等信息。
02
堆栈段的特点是后进先出(LIFO),即最后进入堆栈的元素最先被弹 出。
03
当函数被调用时,其参数和局部变量等信息被压入堆栈中;当函数返 回时,这些信息被从堆栈中弹出。
04
堆栈段的增长和缩小是通过堆栈指针来实现的,堆栈指针指向堆栈的 顶部元素。
PART 02
程序的内存布局
静态内存分配
全局变量存储
代码段
01
代码段用于存储程序的指令代码 ,是程序运行时必须加载到内存 中的部分。
02
代码段通常被划分为多个区段, 每个区段对应程序中的一个模块
或函数。
在程序运行时,代码段中的指令 被加载到CPU的指令寄存器中, 并由CPU执行。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
编译原理
2011年6月7日
12
小结
• 重点掌握: 重点掌握: 静态存储分配 Fortran) 动态存储分 存储分配( 静态存储分配(Fortran)和动态存储分 Pascal) 配(C、Pascal)的含义 活动记录的含义及组成 活动记录的含义及组成 静态、 静态、动态存储分配的策略
编译原理
2011年6月7日
编译原理
2011年6月分配
变量生存期具有嵌套特性, 后进先出的特性(如递归) 变量生存期具有嵌套特性,即后进先出的特性(如递归) 的特性 进入时: 进入时:在栈顶为其分配一个数据区 退出时: 退出时:撤消过程数据区
编译原理
2011年6月7日
10
练习
下面程序的运行结果是什么?如果把第 行的 行的(i+1)*fact( )改 下面程序的运行结果是什么?如果把第6行的 改 的话, 的话 则程序的运行结果是有什么变化? 成fact( )*(i+1)的话,则程序的运行结果是有什么变化?试分析 为什么会有这两种不同的结果。 为什么会有这两种不同的结果。 int fact( ) { static int i=5; if(i==0) return 1; else { i--; return((i+1)*fact( )); //第6行 第 行 }} main( ) { printf("factor of 5!=%d\n",fact());}
一个过程的活动:该过程的一次执行。 一个过程的活动:该过程的一次执行。 活动 即每次执行一个过程体, 即每次执行一个过程体,就产生该过程的 一个活动。 一个活动。 活动记录: 活动记录:为了管理过程在一次执行中所 需要的信息, 需要的信息,使用一段连续的存储区
编译原理
2011年6月7日
5
活动记录的结构
第10章 运行时的存储组织与分配 10章
教学目标
1. 要求明确静态存储分配和动态存储分配的含义 2. 明确活动记录的含义及组成 明确活动记录的含义及组成 了解静态、 3. 了解静态、动态存储分配的策略
编译原理
2011年6月7日
1
S.P 词法分析程序 符 号 表 管 理 语法分析程序 语义分析、 语义分析、生成中间代码 代码优化 生成目标程序 O.P 编译程序在编译阶段要为源程序中出现的变量、 编译程序在编译阶段要为源程序中出现的变量、常量等组 织好在运行阶段的存储空间 织好在运行阶段的存储空间 将这种组织形式通过生成的目标代码 目标代码体现出来 将这种组织形式通过生成的目标代码体现出来 2 为运行阶段实现存储奠定基础 为运行阶段实现存储奠定基础 编译原理 2011年6月7日 错 误 处 理
编译原理
11
2011年6月7日
10.4 堆式动态存储分配
变量生存期具有随机交叉特性,即非后进先出的特性( 变量生存期具有随机交叉特性,即非后进先出的特性(如程序 随机交叉特性 运行时动态申请存储空间) 运行时动态申请存储空间) 给运行的程序划分一个大的存储区(称为 称为堆 给运行的程序划分一个大的存储区 称为堆) 每当需要时可从堆中分得一块 每当需要时可从堆中分得一块 用完之后再退还给堆
TOP 临时变量 内情向量 局部变量 形式单元 静态链 动态链 SP
编译原理
局部数据
连接数据
返回地址
2011年6月7日 6
10.2 静态存储分配
在编译阶段由编译程序实现对存储空间的管理,为 编译阶段由编译程序实现对存储空间的管理, 实现对存储空间的管理 源程序中的变量分配存储单元。 源程序中的变量分配存储单元。
13
条件
在编译时能够确定变量在运行时的数据空间大小 编译时能够确定变量在运行时的数据空间大小 运行时不改变
编译原理
2011年6月7日
7
FORTRAN程序的静态分配 程序的静态分配
主程序的目标代码 子程序 1 的目标代码 …… 子程序 n 的目标代码 全局变量 主程序的活动记录 子程序 1 的活动记录 …… 子程序 n 的活动记录
编译原理
2011年6月7日
8
动态存储分配 在目标程序运行阶段由目标程序实现对存 在目标程序运行阶段由目标程序实现对存 运行阶段 储空间的组织与管理, 储空间的组织与管理,为源程序中的变量分 配存储单元 特点 • 在目标程序运行时进行分配 在目标程序运行时进行分配 • 编译时为运行阶段设计好存储组织形式,即为每个 编译时为运行阶段设计好存储组织形式 设计好存储组织形式, 数据项安排好它在数据区中的相对位置 数据项安排好它在数据区中的相对位置
教学内容
• • • • 10.1 10.2 10.3 10.4 存储组织概述 静态存储分配 栈式动态存储分配 堆式动态存储分配
编译原理
2011年6月7日
3
10.1 存储组织概述
运行时存储空间的划分
代码空间
目标代码空间 静态数据空间 栈 自由空间 堆
数据空间
编译原理
2011年6月7日
4
过程的活动和活动记录