编译原理运行时环境_第1页
编译原理运行时环境_第2页
编译原理运行时环境_第3页
编译原理运行时环境_第4页
编译原理运行时环境_第5页
已阅读5页,还剩58页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、第第7 7章章 运行时环境运行时环境machunyan西北工业大学软件与微电子学院1第第7 7章章 运行时环境运行时环境( (存储空间存储空间) )o 当源程序的目标代码被运行时,在内存中不当源程序的目标代码被运行时,在内存中不仅有目标代码,而且还要保存各种信息仅有目标代码,而且还要保存各种信息n 例如为源程序中出现的一些量(常量、变量及例如为源程序中出现的一些量(常量、变量及某些数组等)分配运行时的存储空间。某些数组等)分配运行时的存储空间。o 目标代码要从操作系统得到一块存储区,用目标代码要从操作系统得到一块存储区,用于它的运行。于它的运行。第第7 7章章 运行时环境运行时环境machun

2、yan西北工业大学软件与微电子学院2o 存储分配是在运行阶段进行的,但存储分配是在运行阶段进行的,但编译程序在编译程序在编译阶段要为其设计好存储组织形式,并将这编译阶段要为其设计好存储组织形式,并将这种组织形式通过生成的目标代码体现出来。种组织形式通过生成的目标代码体现出来。( (举例说明:举例说明:函数调用分析函数调用分析. .txttxt) )o 目标代码运行时,目标代码运行时,存储空间的组织存储空间的组织称为目标代称为目标代码的码的运行时环境运行时环境。第第7 7章章 运行时环境运行时环境( (存储空间存储空间)( )(续续) )第第7 7章章 运行时环境运行时环境machunyan西北

3、工业大学软件与微电子学院3o 运行时环境有三个类型:完全静态环境运行时环境有三个类型:完全静态环境(fully static environment)、基于栈的环境、基于栈的环境(stack-based environment),以及完全动态环境以及完全动态环境(fully dynamic environment)。这这3种类型的混合形种类型的混合形式也是可能的。式也是可能的。第第7 7章章 运行时环境运行时环境( (存储空间存储空间)( )(续续) )第第7 7章章 运行时环境运行时环境machunyan西北工业大学软件与微电子学院4 7.1 7.1 程序执行时的存储器组织程序执行时的存储器

4、组织7.3 7.3 基于栈的运行时环境基于栈的运行时环境7.4 7.4 动态存储器动态存储器7.5 7.5 参数存储机制参数存储机制7.7.2 2 完全静态的运行时环境完全静态的运行时环境第第7 7章章 运行时环境运行时环境( (存储空间存储空间) )第第7 7章章 运行时环境运行时环境machunyan西北工业大学软件与微电子学院57.17.1程序执行时的存储器组织程序执行时的存储器组织目标代码运行时目标代码运行时, ,操作系统为目标代码的运行分配操作系统为目标代码的运行分配的存储空间按用途可划分为下面几个部分的存储空间按用途可划分为下面几个部分: :由于栈区和堆区的长由于栈区和堆区的长度会

5、随着目标代码的度会随着目标代码的运行而变化,因此把运行而变化,因此把它们分配在数据区的它们分配在数据区的两端。一般情况下,两端。一般情况下,栈向下长,堆向上长,栈向下长,堆向上长,可以使栈和堆共用一可以使栈和堆共用一空白存储空间。空白存储空间。第第7 7章章 运行时环境运行时环境machunyan西北工业大学软件与微电子学院67.17.1程序执行时的存储器组织(续)程序执行时的存储器组织(续)o 代码区域:目标代码的存储区域,由于代码区在执行之代码区域:目标代码的存储区域,由于代码区在执行之前是固定的,在编译时所有目标代码的地址都是可计算前是固定的,在编译时所有目标代码的地址都是可计算的,程序

6、执行结束后代码区域内存由系统释放。的,程序执行结束后代码区域内存由系统释放。 o 全程全程/ /静态区域:静态数据区用来存放那些具有绝对地静态区域:静态数据区用来存放那些具有绝对地址的数据和变量址的数据和变量( (如静态变量和全程变量如静态变量和全程变量) );编译器可以编译器可以确定其所占用存储空间的大小,初始化的全局变量和静确定其所占用存储空间的大小,初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域,程序执行结束后由系统静态变量在相邻的另一块区域,程序执行结束后由系统释放。释放。o 本章案例分析本

7、章案例分析.doc.doc第第7 7章章 运行时环境运行时环境7.17.1程序执行时的存储器组织(续)程序执行时的存储器组织(续)o 栈区:栈区:函数中的形参和在函数中定义的局部变量以及局部临时变量(C、C+、Java),这些变量分配在栈区,分配在栈区,每次函数执行的时候会在栈中为函数的执行分配相应的存储区,而在函数执行完毕后,释放相应的存储区。n编译器编译器“知道知道”存在栈中的具体数据所占内存大小和内存分配存在栈中的具体数据所占内存大小和内存分配和释放的和释放的“时刻时刻”;machunyan西北工业大学软件与微电子学院7第第7 7章章 运行时环境运行时环境o 堆区:供用户动态申请存储空间

8、,编译器堆区:供用户动态申请存储空间,编译器“不需要不需要”知知道究竟得从道究竟得从heapheap中分配多少空间,也不需要知道从中分配多少空间,也不需要知道从heapheap上分配的空间究竟需要存在多久。上分配的空间究竟需要存在多久。n 在c中由malloc,free运算产生释放的存储空间,在c+中 由new和delete运算符作用的存储空间,以及在Java中由new分配的存储空间都在堆中进行分配。machunyan西北工业大学软件与微电子学院87.17.1程序执行时的存储器组织(续)程序执行时的存储器组织(续)第第7 7章章 运行时环境运行时环境machunyan西北工业大学软件与微电子学

9、院9第第7 7章章 运行时环境运行时环境machunyan西北工业大学软件与微电子学院10第第7 7章章 运行时环境运行时环境machunyan西北工业大学软件与微电子学院117.17.1程序执行时的存储器组织(续)程序执行时的存储器组织(续)o 在在 语言中语言中, , 采用以函数(或过程)为单位的动态存采用以函数(或过程)为单位的动态存储分配方案:储分配方案:n当一函数被调用时,就在栈顶为该函数分配所需的数据空当一函数被调用时,就在栈顶为该函数分配所需的数据空间间( (过程活动记录过程活动记录) ),当一个函数工作完毕返回时,它在栈,当一个函数工作完毕返回时,它在栈顶的数据空间顶的数据空间

10、( (过程活动记录过程活动记录) )也即释放。也即释放。第第7 7章章 运行时环境运行时环境o 活动记录存放的信息至少应包括以下几个部分:活动记录存放的信息至少应包括以下几个部分:machunyan西北工业大学软件与微电子学院12存放主调函数为被调函数存放主调函数为被调函数提供的实参信息提供的实参信息;存放目标程序临时变存放目标程序临时变量的值量的值;存放本次执行中的局部数据存放本次执行中的局部数据用于指向主调函数的用于指向主调函数的活动记活动记录的控制链录的控制链和返回地址和返回地址;7.17.1程序执行时的存储器组织(续)程序执行时的存储器组织(续)第第7 7章章 运行时环境运行时环境ma

11、chunyan西北工业大学软件与微电子学院137.17.1程序执行时的存储器组织(续)程序执行时的存储器组织(续)实参实参返回地址返回地址控制链控制链临时变量和局部数据临时变量和局部数据实参实参返回地址返回地址控制链控制链临时变量和局部数据临时变量和局部数据调用者调用者的活动的活动记录记录被调用被调用者的活者的活动记录动记录调调用用者者的的职职责责第第7 7章章 运行时环境运行时环境语言所调用函数语言所调用函数的活动记录示例的活动记录示例( (函数调用分析中函数调用分析中的举例的举例) )o 控制链:指向调用函数活动记录的一个地址。machunyan西北工业大学软件与微电子学院14b:2a:1

12、该函数调用结束该函数调用结束时的返回地址时的返回地址(00401014)主调函数的控主调函数的控制链制链c:3栈底栈底栈顶栈顶7.17.1程序执行时的存储器组织(续)程序执行时的存储器组织(续)当前函数的当前函数的控制链控制链第第7 7章章 运行时环境运行时环境machunyan西北工业大学软件与微电子学院157.1 7.1 程序执行时的存储器组织程序执行时的存储器组织7.2 7.2 完全静态的运行时环境完全静态的运行时环境7.3 7.3 基于栈的运行时环境7.4 7.4 动态存储器动态存储器7.5 7.5 参数存储机制参数存储机制第第7 7章章 运行时环境运行时环境( (存储空间存储空间)

13、)第第7 7章章 运行时环境运行时环境machunyan西北工业大学软件与微电子学院167.2 7.2 完全静态的运行时环境完全静态的运行时环境o 在完全静态环境中,不仅全局变量,所有的变量都是在完全静态环境中,不仅全局变量,所有的变量都是静态分配,即整个程序所需数据空间的总量在编译时静态分配,即整个程序所需数据空间的总量在编译时是完全确定的,从而每个数据名的地址就可静态地进是完全确定的,从而每个数据名的地址就可静态地进行分配,适于静态分配的语言,要求满足的条件是:行分配,适于静态分配的语言,要求满足的条件是:n每个数据名所需的存储空间的大小都是常量每个数据名所需的存储空间的大小都是常量n不允

14、许采用动态的数据结构,即在程序运行过程中申请或释不允许采用动态的数据结构,即在程序运行过程中申请或释放的数据结构放的数据结构n过程不可递归调用过程不可递归调用第第7 7章章 运行时环境运行时环境machunyan西北工业大学软件与微电子学院17整个程序整个程序存储器如存储器如右所示:右所示:7.2 7.2 完全静态的运行时环境(续)完全静态的运行时环境(续)第第7 7章章 运行时环境运行时环境machunyan西北工业大学软件与微电子学院187.1 7.1 程序执行时的存储器组织程序执行时的存储器组织7.2 7.2 完全静态的运行时环境完全静态的运行时环境7.3 7.3 基于栈的运行时环境基于

15、栈的运行时环境7.4 7.4 动态存储器动态存储器7.5 7.5 参数存储机制参数存储机制第第7 7章章 运行时环境运行时环境( (存储空间存储空间) )第第7 7章章 运行时环境运行时环境machunyan西北工业大学软件与微电子学院197.3 7.3 基于栈的运行时环境基于栈的运行时环境o 在一个在一个所有函数都是全局的所有函数都是全局的、函数、函数定义不允定义不允许嵌套许嵌套,但允许函数递归调用的程序设计语,但允许函数递归调用的程序设计语言言( (例如例如C C语言语言) )中,基于栈的动态运行时环中,基于栈的动态运行时环境有两个指针境有两个指针:n sp:栈顶部栈顶部( (top of

16、 stack) )指针;对于指针;对于x86x86系统来系统来说,它采用说,它采用spsp或或espesp寄存器存储栈顶部的地址;寄存器存储栈顶部的地址;n 注:用它只可访问栈顶注:用它只可访问栈顶第第7 7章章 运行时环境运行时环境machunyan西北工业大学软件与微电子学院207.3 7.3 基于栈的运行时环境(续)基于栈的运行时环境(续)n fp(frame point):控制链指针,即存储控制链指针,即存储当前活当前活动记录的控制链(即一个地址)动记录的控制链(即一个地址),对于对于x86系系统,它采用统,它采用bp或或ebp寄存器寄存器存储存储当前活动记录当前活动记录的控制链,其作

17、用如下:的控制链,其作用如下:o 1.1.通过该指针可以访问主调函数的活动记录;即允通过该指针可以访问主调函数的活动记录;即允许在当前的被调函数执行完毕时,用它来恢复主调许在当前的被调函数执行完毕时,用它来恢复主调函数的活动记录。函数的活动记录。o 2.2.通过该指针可以访问当前执行函数的实参和局部通过该指针可以访问当前执行函数的实参和局部变量;变量;第第7 7章章 运行时环境运行时环境machunyan西北工业大学软件与微电子学院21b:2a:1该函数调用结束该函数调用结束时的返回地址时的返回地址(cs:eip) 00401014主调函数的控主调函数的控制链制链(main.ebp)void

18、_stdcall void _stdcall f_stdcall(int f_stdcall(int a,int b)a,int b) int c;int c;c=a+b;c=a+b; c:3esp栈底栈底栈顶栈顶ebp7.3 7.3 基于栈的运行时环境(续)基于栈的运行时环境(续)第第7 7章章 运行时环境运行时环境machunyan西北工业大学软件与微电子学院22当一个函数被调用时,当一个函数被调用时,在栈顶为该函数分配在栈顶为该函数分配所需的数据空间所需的数据空间( (过程活动记录过程活动记录) )如下:如下:1)1) 将将实参实参的值压入在该函数对应的的值压入在该函数对应的新活动记录新

19、活动记录中。中。2)2) 将被调函数执行完毕后的将被调函数执行完毕后的返回地址返回地址压入在压入在新的活动记录新的活动记录中。中。3)3) 完成到被调用的过程代码一个转移。完成到被调用的过程代码一个转移。4)4) 将主调函数的将主调函数的fpfp作为作为控制链压入到新的活动记录控制链压入到新的活动记录中。中。5)5) 改变改变fpfp以使其以使其指向新的活动记录指向新的活动记录( (将将spsp复制到复制到fpfp中中) )6)6) 将该函数的将该函数的局部变量局部变量和和局部临时变量局部临时变量压入到新的活动记录中。压入到新的活动记录中。7.3 7.3 基于栈的运行时环境(续)基于栈的运行时

20、环境(续)第第7 7章章 运行时环境运行时环境machunyan西北工业大学软件与微电子学院23b:2a:1该函数调用结束该函数调用结束时的返回地址时的返回地址(cs:eip) 00401014主调函数的控主调函数的控制链制链(main.fp)语言当前执语言当前执行函数的活动行函数的活动记录示例:记录示例:c:3sp栈底栈底栈顶栈顶fp7.3 7.3 基于栈的运行时环境(续)基于栈的运行时环境(续)第第7 7章章 运行时环境运行时环境machunyan西北工业大学软件与微电子学院24当被调函数执行完毕返回时,其对应当被调函数执行完毕返回时,其对应的活动记录从栈中弹出的过程:的活动记录从栈中弹出

21、的过程: 将将fpfp复制到复制到spsp中。中。 将控制链装载到将控制链装载到fpfp中。中。 完成到返回地址主调函数的一个转移。完成到返回地址主调函数的一个转移。 改变改变spsp以弹出实参。以弹出实参。7.3 7.3 基于栈的运行时环境(续)基于栈的运行时环境(续)第第7 7章章 运行时环境运行时环境machunyan西北工业大学软件与微电子学院25例:计算两个非负整数最大公约数的例:计算两个非负整数最大公约数的c c代码如下:代码如下:#include int x,y;int gcd(int u,int v) if(v= =0) return u; else return gcd(v,

22、u%v)main() scanf(“%d%d”,&x,&y); printf(“%dn”,gcd(x,y); return 0;7.3 7.3 基于栈的运行时环境(续)基于栈的运行时环境(续)第第7 7章章 运行时环境运行时环境machunyan西北工业大学软件与微电子学院26x:15x:15y:10y:10全局全局/ /静态区域静态区域mainmain的活动记录的活动记录sp,fpsp,fpv:10v:10u:15u:15返回地址返回地址mainmain的的fpfp第一次调用第一次调用gcdgcd时的活动记录时的活动记录sp,fpsp,fp第二次调用第二次调用gcdgcd时的活动记录时的活动

23、记录v:5v:5u:10u:10返回地址返回地址第一次调用第一次调用gcdgcd时的时的fpfp第三次调用第三次调用gcdgcd时的活动记录时的活动记录v:0v:0u:5u:5返回地址返回地址第二次调用第二次调用gcdgcd时的时的fpfpsp,fpsp,fpsp,fpsp,fp栈生长方向栈生长方向自由空间自由空间7.3 7.3 基于栈的运行时环境(续)基于栈的运行时环境(续)第第7 7章章 运行时环境运行时环境machunyan西北工业大学软件与微电子学院27例:考虑下列程序清单的例:考虑下列程序清单的c c代码。代码。int x=2;void g(int);void f(int n)sta

24、tic int x=1; g(n); x- -;void g(int m)int y=m-1;if (y0) f(y); x- -; g(y); main()g(x); return 0;画出至第二次对画出至第二次对g调用时,调用时,程序的运行时环境:程序的运行时环境:7.3 7.3 基于栈的运行时环境(续)基于栈的运行时环境(续)第第7 7章章 运行时环境运行时环境machunyan西北工业大学软件与微电子学院28x:2x:2x x(from ffrom f):1:1全局全局/ /静态区域静态区域mainmain的活动记录的活动记录sp,fpsp,fpm:2m:2返回地址返回地址mainma

25、in的的fp fp y:1y:1第一次调用第一次调用g g时时的活动记录的活动记录fpfpspsp第一次调用第一次调用f f时时的活动记录的活动记录n:1n:1 返回地址返回地址第一次调用第一次调用g g时的时的fpfpsp,fpsp,fp第二次调用第二次调用g g时的时的活动记录活动记录m:1m:1 返回地址返回地址第一次调用第一次调用f f时的时的fp fp y:0y:0fpfpspsp栈生长方向栈生长方向自由空间自由空间7.3 7.3 基于栈的运行时环境(续)基于栈的运行时环境(续)第第7 7章章 运行时环境运行时环境machunyan西北工业大学软件与微电子学院29o 目标代码的生成必

26、须目标代码的生成必须n 支持变量和临时变量的实际定位,并增加支持运支持变量和临时变量的实际定位,并增加支持运行时环境所必需的代码行时环境所必需的代码。 对名字的访问对名字的访问o 局部临时变量局部临时变量o 嵌套声明嵌套声明o 如何处理可变长度的问题如何处理可变长度的问题7.3 7.3 基于栈的运行时环境(续)基于栈的运行时环境(续)第第7 7章章 运行时环境运行时环境machunyan西北工业大学软件与微电子学院30对名字的访问:对名字的访问:o 在没有局部过程的基于栈的运行时环境中,所有的非在没有局部过程的基于栈的运行时环境中,所有的非局部的名字都是全局的局部的名字都是全局的,因此也就是静

27、态的,都具有,因此也就是静态的,都具有一个固定的静态地址,可以被直接访问。一个固定的静态地址,可以被直接访问。o 对函数参数和局部变量而言,在大多数的语言中,如对函数参数和局部变量而言,在大多数的语言中,如果函数的声明在编译时是固定的,而且为每个声明分果函数的声明在编译时是固定的,而且为每个声明分配的存储器大小也根据其数据类型而固定,配的存储器大小也根据其数据类型而固定,每个实参每个实参和局部声明的偏移量可由编译程序计算和局部声明的偏移量可由编译程序计算。第第7 7章章 运行时环境运行时环境machunyan西北工业大学软件与微电子学院31m:2 m:2 返回地址返回地址控制链控制链 y:1y

28、:1fpfpmOffsetmOffsetyOffsetyOffsetmOffset=+8mOffset=+8yOffset=-4yOffset=-4高端地址高端地址低端地址低端地址对名字的访问:(续)对名字的访问:(续)第第7 7章章 运行时环境运行时环境machunyan西北工业大学软件与微电子学院32例:考虑下面的例:考虑下面的C C过程过程Viod f(int x,char c)Viod f(int x,char c)int a10;int a10; double y; double y; c cx x 返回地址返回地址控制链控制链a9a9a1a1a0a0y yfpfpcOffsetcO

29、ffsetaOffsetaOffsetxOffsetxOffsetyOffsetyOffsetxOffset=+8xOffset=+8cOffset=+12cOffset=+12aOffset=-40aOffset=-40yOffset=-48yOffset=-48现在对现在对aiai访问,要求计算地址:访问,要求计算地址:(-40+4(-40+4* *i)(fp)i)(fp)对名字的访问:(续)对名字的访问:(续)对对f调用的活动记录为:调用的活动记录为:第第7 7章章 运行时环境运行时环境machunyan西北工业大学软件与微电子学院33o 目标代码的生成必须目标代码的生成必须n 支持变量

30、和临时变量的实际定位,并增加支持运支持变量和临时变量的实际定位,并增加支持运行时环境所必需的代码行时环境所必需的代码。o 对名字的访问对名字的访问 局部临时变量局部临时变量o 嵌套声明嵌套声明o 如何处理可变长度的问题如何处理可变长度的问题7.3 7.3 基于栈的运行时环境(续)基于栈的运行时环境(续)第第7 7章章 运行时环境运行时环境machunyan西北工业大学软件与微电子学院34局部临时变量:局部临时变量:o 考虑考虑C表达式:表达式:xi=(i+j)*(i/k+f(j),在这个,在这个表达式从左到右的求值计算中,在对表达式从左到右的求值计算中,在对f的调的调用过程中需要保存中间结果:

31、用过程中需要保存中间结果: xi的地址、的地址、i+j的和、的和、i/k的商。的商。n 这些中间值可计算到寄存器中,根据寄存器进这些中间值可计算到寄存器中,根据寄存器进行保存和恢复;或者行保存和恢复;或者可将它们作为临时变量存可将它们作为临时变量存储在对储在对f调用之前的运行时栈中调用之前的运行时栈中。如下所示:。如下所示:第第7 7章章 运行时环境运行时环境machunyan西北工业大学软件与微电子学院35 返回地址返回地址控制链控制链xixi的地址的地址i+ji+j的结果的结果i/ji/j的结果的结果fpfp( (栈的其余部分栈的其余部分) )spsp临时栈临时栈调用调用f f(将要创建的

32、)时的将要创建的)时的新活动记录新活动记录包含表达式过程的活动记录包含表达式过程的活动记录自由空间自由空间局部临时变量:(续)局部临时变量:(续)第第7 7章章 运行时环境运行时环境machunyan西北工业大学软件与微电子学院36o 目标代码的生成必须目标代码的生成必须n 支持变量和临时变量的实际定位,并增加支持运支持变量和临时变量的实际定位,并增加支持运行时环境所必需的代码行时环境所必需的代码。o 对名字的访问对名字的访问p 局部临时变量局部临时变量p 嵌套声明嵌套声明o 如何处理可变长度的问题如何处理可变长度的问题7.3 7.3 基于栈的运行时环境(续)基于栈的运行时环境(续)第第7 7

33、章章 运行时环境运行时环境machunyan西北工业大学软件与微电子学院37嵌套声明也出现了与局部临时变量同样的问题。考虑以下的嵌套声明也出现了与局部临时变量同样的问题。考虑以下的C C代码:代码:Void p(int x,double y) char a; int i; A: double x; int j; B: char *a; int k; 嵌套声明:嵌套声明:第第7 7章章 运行时环境运行时环境machunyan西北工业大学软件与微电子学院38x:x:y:y: 返回地址返回地址 控制链控制链a:a:i:i:x x: :j j: :fpfp( (栈的其余部分栈的其余部分) )spsp块

34、块A A的分配区的分配区调用调用p p时的活动记录时的活动记录自由空间自由空间嵌套声明:(续)嵌套声明:(续)o一个简单的处理办法是按照与临时表达式相类似的办法在嵌套一个简单的处理办法是按照与临时表达式相类似的办法在嵌套的块中处理声明,并在进入块时在栈中分配它们。当进入块的块中处理声明,并在进入块时在栈中分配它们。当进入块A后,运行时栈如下所示:后,运行时栈如下所示:第第7 7章章 运行时环境运行时环境machunyan西北工业大学软件与微电子学院39x:x:y:y: 返回地址返回地址控制链控制链a:a:i:i:a a: :k k: :fpfp( (栈的其余部分栈的其余部分) )spsp块块B

35、 B的分配区的分配区调用调用p p时的活动记录时的活动记录自由空间自由空间当进入块当进入块B B后,运行时栈如下所示:后,运行时栈如下所示:嵌套声明:(续)嵌套声明:(续)第第7 7章章 运行时环境运行时环境machunyan西北工业大学软件与微电子学院40o 目标代码的生成必须目标代码的生成必须n 支持变量和临时变量的实际定位,并增加支持运支持变量和临时变量的实际定位,并增加支持运行时环境所必需的代码行时环境所必需的代码。o 对名字的访问对名字的访问p 局部临时变量局部临时变量p 嵌套声明嵌套声明 如何处理可变长度的问题如何处理可变长度的问题7.3 7.3 基于栈的运行时环境(续)基于栈的运

36、行时环境(续)第第7 7章章 运行时环境运行时环境machunyan西北工业大学软件与微电子学院41处理可变长度的数据处理可变长度的数据有时编译程序必须处理数据变化的可能性,表现在数据对象的数量和每有时编译程序必须处理数据变化的可能性,表现在数据对象的数量和每个对象的大小上。发生在支持基于栈的环境的语言中的一种情况如下:个对象的大小上。发生在支持基于栈的环境的语言中的一种情况如下: 调用中的自变量的数量可根据调用的不同而不同。调用中的自变量的数量可根据调用的不同而不同。printf(printf(“%d%s, n, prompt);%d%s, n, prompt);printf(printf(

37、“%d %d %d %d %d %d ”,3,4,50);,3,4,50);通常,通常,C C编译程序一般通过把调用的自变量按相反顺序编译程序一般通过把调用的自变量按相反顺序( (in reverse in reverse order)order)压入到运行时栈来处理这一点。压入到运行时栈来处理这一点。第第7 7章章 运行时环境运行时环境machunyan西北工业大学软件与微电子学院42oprintf(“%d %d %d” ,3,4,50); 设置一指针设置一指针ap; 让让ap指向第一个可变参数指向第一个可变参数(地址为地址为ebp+控制链所占的空控制链所占的空间间+返回地址所占的空间返回地

38、址所占的空间+固定参数所占的空间固定参数所占的空间),即,即3所所在的空间;在的空间; 返回返回3,ap的值加的值加4即指向即指向4所在的存储空间所在的存储空间,通过指通过指针针ap的移动读取所有的可变参数,根据固定参数的移动读取所有的可变参数,根据固定参数“%d %d %d”,该字符串中每出现一个,该字符串中每出现一个“%d”就执行一次;就执行一次;固定参数指出了后面的可固定参数指出了后面的可变参数的个数;变参数的个数; 清除变量清除变量ap。处理可变长度的数据处理可变长度的数据(续续)第第7 7章章 运行时环境运行时环境machunyan西北工业大学软件与微电子学院437.1 7.1 程序

39、执行时的存储器组织程序执行时的存储器组织7.2 7.2 完全静态的运行时环境完全静态的运行时环境7.3 7.3 基于栈的运行时环境基于栈的运行时环境7.4 7.4 动态存储器动态存储器7.5 7.5 参数存储机制参数存储机制第第7 7章章 运行时环境运行时环境( (存储空间存储空间) )第第7 7章章 运行时环境运行时环境machunyan西北工业大学软件与微电子学院447.4.1对象类型对象类型在大多数面向对象的语言中,对象都有构造函数和在大多数面向对象的语言中,对象都有构造函数和析构函数,它们分别在创建对象和释放对象时被调析构函数,它们分别在创建对象和释放对象时被调用。假定我们有一对象类用

40、。假定我们有一对象类A A,它有方法它有方法m1,m2m1,m2以及字段以及字段a1a1和和a2a2。那么类那么类A A对象的运行时表示有包含对象的运行时表示有包含字段字段a1a1和和a2a2记录组成:记录组成:a1a1a2a2m1_Am1_Am2_Am2_A另外,编译程序维护着一张类另外,编译程序维护着一张类A A的编译时方法表:的编译时方法表:7.4 7.4 动态存储器动态存储器第第7 7章章 运行时环境运行时环境o 在上述简单的模块中,字段选择可以像记录字在上述简单的模块中,字段选择可以像记录字段选择一样实现,方法选择由编译程序内的识段选择一样实现,方法选择由编译程序内的识别过程来实现。

41、即通过一个指向对象的指针,别过程来实现。即通过一个指向对象的指针,方法可以像函数一样实现。因此方法方法可以像函数一样实现。因此方法m2_Am2_A可以可以翻译为翻译为c c语言中的函数。语言中的函数。n void m2_A(class_A *this, int i) 方法方法m2_A的程序体,通过的程序体,通过this-x访问访问 任一对任一对 象字段象字段x 方法的调用方法的调用a .m2(3)a .m2(3)可以翻译成可以翻译成m2_A(&a,3)m2_A(&a,3)machunyan西北工业大学软件与微电子学院457.4 7.4 动态存储器(续)动态存储器(续)第第7 7章章 运行时环境

42、运行时环境machunyan西北工业大学软件与微电子学院46继承特性继承特性现在假定类现在假定类B B通过增添方法通过增添方法m3m3和字段和字段b1b1来扩展类来扩展类A,A,那么类那么类B B的运行时表示如下:的运行时表示如下:a1a1a2a2m1_Am1_Am2_Am2_Ab1b1另外类另外类B B的方法编译时表如下:的方法编译时表如下:m3_Bm3_B7.4 7.4 动态存储器(续)动态存储器(续)第第7 7章章 运行时环境运行时环境machunyan西北工业大学软件与微电子学院47方法重载方法重载假定上例中类假定上例中类B B重新定义了方法重新定义了方法m2m2,那么那么A A中方法

43、中方法m2m2的定义既是它唯的定义既是它唯一的声明也是它的第一次定义,而它在类一的声明也是它的第一次定义,而它在类B B中的定义为重定义。中的定义为重定义。为使名字既可以反映声明它的类,也可以反映定义它的类。方法的为使名字既可以反映声明它的类,也可以反映定义它的类。方法的名字可有三部分组成:名字可有三部分组成:方法名、声明方法的类名、定义方法类名方法名、声明方法的类名、定义方法类名。各部分之间用下划线(各部分之间用下划线()分开。因此在类)分开。因此在类A A中声明在类中声明在类B B中定义的中定义的方法方法m2m2其名字记为其名字记为m2_A_Bm2_A_B。方法重载影响方法的编译时表,现在

44、类方法重载影响方法的编译时表,现在类A A的方法的编译时表如下:的方法的编译时表如下:m1_A_Am1_A_Am2_A_Am2_A_Am1_A_Am1_A_Am2_A_Bm2_A_Bm3_B_Bm3_B_B类类B B的方法的的方法的编译时表如右:编译时表如右:7.4 7.4 动态存储器(续)动态存储器(续)第第7 7章章 运行时环境运行时环境o 现在假定现在假定a是类是类A的一个对象,而的一个对象,而b是类是类B的一个对象的一个对象n 方法调用方法调用a.m2()将翻译成对将翻译成对m2_A_A的调用,而方的调用,而方法调用法调用b.m2()将翻译成对将翻译成对m2_A_B的调用。的调用。o

45、2_A_A在类在类A中声明和定义。中声明和定义。m2_A_B在类在类A中生明,在中生明,在类类B中定义。中定义。n m2_A_A翻译形式为:翻译形式为:o void m2_A_A(Class_A *this, int i);n m2_A_B的翻译形式为:的翻译形式为:o void m2_A_B(Class_B *this, int i);machunyan西北工业大学软件与微电子学院487.4 7.4 动态存储器(续)动态存储器(续)第第7 7章章 运行时环境运行时环境machunyan西北工业大学软件与微电子学院49多态性多态性当类当类B B继承类继承类A A,并且该语言允许,并且该语言允许

46、“类类B B的指针的指针”类型的指针类型的指针能够赋给一个能够赋给一个“类类A A的指针的指针”类型的变量时,那么该语言类型的变量时,那么该语言支持多态型。例如:支持多态型。例如: Class B Class B * *b=b=; ; Class A Class A * *a=b;a=b;则第二行被翻译成:则第二行被翻译成: class A class A * *a=convert_ptr_to_B_to_ptr_to_A(b);a=convert_ptr_to_B_to_ptr_to_A(b);现在,过程现在,过程convert_ptr_to_B_to_ptr_to_A()convert_p

47、tr_to_B_to_ptr_to_A()为一编译为一编译时类型的操作时类型的操作, ,它将指向子类它将指向子类B B的一个对象指针转换为指的一个对象指针转换为指向其父类向其父类A A对象的指针。因为类对象的指针。因为类B B的对象也是从类的对象也是从类A A的字的字段开始,因而指针的值并不需要改变,唯一影响的是改段开始,因而指针的值并不需要改变,唯一影响的是改变了指针的类型:变了指针的类型:7.4 7.4 动态存储器(续)动态存储器(续)第第7 7章章 运行时环境运行时环境machunyan西北工业大学软件与微电子学院50a1a1a2a2b1b1指向指向B B的指针的指针指向指向B B中中A

48、 A的指针的指针现在同一指针指向了不同类的对象现在同一指针指向了不同类的对象7.4 7.4 动态存储器(续)动态存储器(续)第第7 7章章 运行时环境运行时环境machunyan西北工业大学软件与微电子学院517.4 7.4 动态存储器(续)动态存储器(续)o 动态绑定动态绑定:类型:类型class Aclass A* *的指针的指针p p可能引用了类可能引用了类B B的一个的一个对象,动态绑定认为如果实际上为类对象,动态绑定认为如果实际上为类B B的对象,那就应该的对象,那就应该调用调用m2_A_B,m2_A_B,如果实际为如果实际为A A的对象,那么就应该调用的对象,那么就应该调用m2_A

49、_A.m2_A_A.对于方法调用对于方法调用p-m2(3)p-m2(3)o p p是一指向类是一指向类A A对象指针,可以将对象指针,可以将p-m2(3)p-m2(3)被翻译成如下被翻译成如下形式:形式: switch(dynamic_type_of(p) case Dynamic_class_A: m2_A_A(p,3); case Dynamic_class_B: m2_A_B(convert_ptr_to_A_to_ptr_to_B(p),3);o 当当p p为一指向类为一指向类B B对象指针时,可以将对象指针时,可以将p-m2(3)p-m2(3) 翻译为:翻译为:m2_A_B(p,3)

50、;m2_A_B(p,3);第第7 7章章 运行时环境运行时环境machunyan西北工业大学软件与微电子学院52对于上述的翻译方法,每一个对象的类型信息实现为一个对于上述的翻译方法,每一个对象的类型信息实现为一个指向分派表的指针,如下图所示指向分派表的指针,如下图所示( (分派表是存储方法地址分派表是存储方法地址的记录,下图分派表存储的是方法的记录,下图分派表存储的是方法m1_A_Am1_A_A, m2_A_B m2_A_B和和 m1_B_Bm1_B_B的地址的地址) )a1a1a2a2b1b1指向指向B B的指针的指针指向指向B B中中A A的指针的指针m1_A_Am1_A_Am2_A_Bm

51、2_A_Bm3_B_Bm3_B_B类类B B对象的表示对象的表示分派表分派表B-objectB-objectB-classB-class7.4 7.4 动态存储器(续)动态存储器(续)第第7 7章章 运行时环境运行时环境machunyan西北工业大学软件与微电子学院537.4.2 堆管理堆管理7.4 7.4 动态存储器(续)动态存储器(续)o 对于允许程序为变量在运行时动态申请和释对于允许程序为变量在运行时动态申请和释放存储空间的语言放存储空间的语言,采用堆式分配是最有效采用堆式分配是最有效的解决方案的解决方案.o 堆式分配的基本思想是堆式分配的基本思想是,为运行的程序划出为运行的程序划出适当

52、大的空间适当大的空间(称为堆称为堆Heap),每当程序申请空每当程序申请空间时间时,就从堆的空闲区找出一块空间分配给就从堆的空闲区找出一块空间分配给程序程序,每当释放时则回收之每当释放时则回收之.第第7 7章章 运行时环境运行时环境machunyan西北工业大学软件与微电子学院54堆分配的必要性堆分配的必要性7.4 7.4 动态存储器(续)动态存储器(续)o在在C中处理链表等结构时中处理链表等结构时,常常随机地插入或删除一些结点常常随机地插入或删除一些结点,利用利用指针变量和结构类型指针变量和结构类型,可动态地生成新结点可动态地生成新结点(使用使用malloc()函数函数), 或删除之或删除之

53、(使用使用free()函数函数).o例如例如 struct node char data; struct node *next;定义了链表的结定义了链表的结点点,下面函数可在表的尾部添加新结点下面函数可在表的尾部添加新结点:n void Append(struct node *head,char ch) struct node *p=head;n while(*p) p=p-next; p-next=malloc(sizeof(struct node);n p-next-data=ch; p-next-next=NULL;o还可用下面的函数在表头删除一结点还可用下面的函数在表头删除一结点:nv

54、oid Delete(struct node *head) struct node *p=head; n if(*p) head =head-next; free(p); 第第7 7章章 运行时环境运行时环境machunyan西北工业大学软件与微电子学院55堆存储管理的实现堆存储管理的实现7.4 7.4 动态存储器(续)动态存储器(续)o 将存储空间划分为若干存储块将存储空间划分为若干存储块;用户可随机地申请用户可随机地申请或释放一个或多个块或释放一个或多个块;o 在存储空间中建立两个队列在存储空间中建立两个队列:空闲队列和忙队列空闲队列和忙队列,空空闲队列拉成链闲队列拉成链,链首用链首用FR

55、EE指针指明指针指明,忙队列用一忙队列用一(已占块已占块)记录表记录各占用块的首址及大小信息记录表记录各占用块的首址及大小信息(也也可用链进行记录可用链进行记录).o 申请时可按需要找到合适的块分配之申请时可按需要找到合适的块分配之(分配策略有分配策略有最佳分配或随机分配等最佳分配或随机分配等);o 释放时将该块插入到空闲队列释放时将该块插入到空闲队列(能合并时可合并能合并时可合并),并并从占用记录表中删除相应的项从占用记录表中删除相应的项.第第7 7章章 运行时环境运行时环境machunyan西北工业大学软件与微电子学院567.1 7.1 程序执行时的存储器组织程序执行时的存储器组织7.2

56、7.2 完全静态的运行时环境完全静态的运行时环境7.3 7.3 基于栈的运行时环境基于栈的运行时环境7.4 7.4 动态存储器动态存储器7.5 7.5 参数存储机制参数存储机制第第7 7章章 运行时环境运行时环境( (存储空间存储空间) )第第7 7章章 运行时环境运行时环境machunyan西北工业大学软件与微电子学院577.5 7.5 参数传递机制参数传递机制void inc2( int x)/* incorrect! */ +x;+x; void inc2( int* x)/* now ok */ +(*x);+(*x); o 值传递值传递:值传递的处理方法是:进入过程时值传递的处理方法

57、是:进入过程时,送入形参对应的形式送入形参对应的形式单元的是相应实参的值单元的是相应实参的值;过程体中对形参的任何赋值都按对形式;过程体中对形参的任何赋值都按对形式单元的直接访问来产生代码。形参和实参不是同一个存储单元。单元的直接访问来产生代码。形参和实参不是同一个存储单元。n因此因此,一旦把实参之值送入对应形式单元之后一旦把实参之值送入对应形式单元之后,在执行过程体期间在执行过程体期间,除了以实参值作为形参的初值进行运算之外除了以实参值作为形参的初值进行运算之外,将将不再与实参发生任不再与实参发生任何联系。由此可见何联系。由此可见, 过过 程执行的结果决不会改变实参之值。程执行的结果决不会改变实参之值。第第7 7章章 运行时环境运行时环境machunyan西北工业大学软件与微电子学院58void inc2( int &x)/* C+ reference parameter */ +x;+x; 7.5 7.5 参数传递机制(续)参数传递机制(续)o 引用传递引用传递:将实参的地址写入相应

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论