编译器设计-RunTime运行时环境
编译器设计-RunTime运行时环境
Compiler Design - Run-Time Environment
作为源代码的程序仅仅是文本(代码、语句等)的集合,要使其活动,它需要在目标计算机上执行操作。程序需要内存资源来执行指令。程序包含程序名、标识符等,运行时需要与实际内存位置进行映射。
所谓运行时,我们指的是正在执行的程序。运行时环境是目标机器的一种状态,它可以包括软件库、环境变量等,为系统中运行的进程提供服务。
运行时支持系统是一个包,主要由可执行程序本身生成,有助于进程与运行时环境之间的进程通信。它在执行程序时负责内存分配和取消分配。
激活树Activation Trees
程序是一系列指令组合成若干过程的序列。过程中的指令是按顺序执行的。过程有一个开始和结束分隔符,其中的所有内容都称为过程的主体。过程标识符及其内部的有限指令序列构成了过程的主体。
过程的执行称为其激活。激活记录包含调用过程所需的所有必要信息。激活记录可以包含以下单元(取决于使用的源语言)。

每当执行一个过程时,它的激活记录都存储在堆栈上,也称为控制堆栈。当一个过程调用另一个过程时,调用方的执行将被挂起,直到被调用的过程完成执行为止。此时,被调用过程的激活记录存储在堆栈上。
我们假设程序控制按顺序执行,当一个过程被调用时,它的控制权被转移到被调用的过程。当被调用的过程被执行时,它将控件返回给调用方。这种类型的控制流使以树(称为激活树)的形式表示一系列激活变得更容易。
为了理解这个概念,我们以一段代码为例:
. . .
printf(“Enter Your Name: “);
scanf(“%s”, username);
show_data(username);
printf(“Press any key to continue…”);
. . .
int show_data(char *user)
{
printf(“Your name is %s”, username);
return 0;
}
. . .
下面是给定代码的激活树。

现在我们知道过程是以深度优先的方式执行的,因此堆栈分配是过程激活的最佳存储形式。
存储分配Storage Allocation
运行时环境管理以下实体的运行时内存需求:
代码:它被称为程序的文本部分,在运行时不会更改。它的内存需求在编译时是已知的。
过程:它们的文本部分是静态的,但它们是以随机的方式调用的。这就是为什么堆栈存储用于管理过程调用和激活。
变量:变量只有在运行时才知道,除非它们是全局变量或常量。堆内存分配方案用于管理运行时变量的内存分配和取消分配。
静态分配Static Allocation
在这种分配方案中,编译数据被绑定到内存中的一个固定位置,并且在程序执行时不会改变。由于预先知道内存需求和存储位置,因此不需要内存分配和取消分配的运行时支持包。
堆栈分配Stack Allocation
过程调用及其激活通过堆栈内存分配进行管理。它适用于后进先出(LIFO)方法,这种分配策略对于递归过程调用非常有用。
Heap Allocation
仅在运行时才分配和取消分配过程本地的变量。堆分配用于动态地将内存分配给变量,并在不再需要变量时将其收回。
除了静态分配的内存区域外,堆栈和堆内存都可以动态和意外地增长和收缩。因此,不能在系统中为它们提供固定数量的内存。

如上图所示,代码的文本部分被分配了固定数量的内存。堆栈和堆内存被安排在分配给程序的总内存的最末端。两个人都在互相残杀和成长。
参数传递Parameter Passing
过程之间的通信媒介称为参数传递。调用过程中的变量值通过某种机制传递给被调用过程。在继续之前,先复习一些与程序中的值有关的基本术语。
右值
表达式的值称为其r值。如果包含在单个变量中的值出现在赋值运算符的右侧,则该值也将变为r值。r值总是可以分配给其他变量。
l值
存储表达式的内存(地址)的位置称为该表达式的l值。它总是出现在赋值运算符的左侧。
For example:
day = 1;
week = day * 7;
month = 1;
year = month * 12;
从这个例子中,我们了解到常数值(如1、7、12)和变量(如日、周、月和年)都有r值。只有变量才有l值,因为它们也表示分配给它们的内存位置。
For example:
7 = x + y;
是一个l值错误,因为常量7不代表任何内存位置。
形式参数Formal Parameters
接受调用方过程传递的信息的变量称为形式参数。这些变量在被调用函数的定义中声明。
实际参数Actual Parameters
将其值或地址传递给被调用过程的变量称为实际参数。这些变量在函数调用中指定为参数。
Example:
fun_one()
{
int actual_parameter = 10;
call fun_two(int actual_parameter);
}
fun_two(int formal_parameter)
{
print formal_parameter;
}
形式参数保存实际参数的信息,这取决于所使用的参数传递技术。它可以是一个值或地址。
传递值Pass by Value
在传递值机制中,调用过程传递实际参数的r值,编译器将其放入被调用过程的激活记录中。然后,形式参数保存调用过程传递的值。如果形式参数所保留的值发生了更改,则不会对实际参数产生影响。
通过引用传递Pass by Reference
在按引用传递机制中,实际参数的l值被复制到被调用过程的激活记录中。这样,被调用的过程现在拥有实际参数的地址(内存位置),而形式参数引用相同的内存位置。因此,如果更改了形式参数所指向的值,则应该看到对实际参数的影响,因为它们也应该指向相同的值。
按副本传递还原Pass by Copy-restore
此参数传递机制的工作原理与“按引用传递”类似,只是在调用过程结束时对实际参数进行更改。在函数调用时,实际参数的值被复制到被调用过程的激活记录中。如果操作了形式参数,则对实际参数没有实时影响(因为传递了l值),但是当调用过程结束时,形式参数的l值将复制到实际参数的l值。
例子:
Example:
int y;
calling_procedure()
{
y = 10;
copy_restore(y); //l-value of y is passed
printf y; //prints 99
}
copy_restore(int x)
{
x = 99; // y still has value 10 (unaffected)
y = 0; // y is now 0
}
此函数结束时,形式参数x的l值复制到实际参数y,即使在过程结束前改变了y值,x的l值也复制到y的l值,使其行为类似于通过引用调用。
按名称传递Pass by Name
像Algol这样的语言提供了一种新的参数传递机制,其工作原理类似于C语言中的预处理器。在按名称传递机制中,被调用的过程的名称将被其实际主体替换。Pass by name以文本方式将过程调用中的参数表达式替换为过程主体中的相应参数,以便它现在可以处理实际参数,这与Pass by reference非常类似。
编译器设计-RunTime运行时环境的更多相关文章
- 运行时环境(The Runtime Environment)
App Engine应用响应网络请求.当一个客户端(典型的是用户的Web浏览器)使用HTTP请求(比如获取在URL上的网页)连接上应用的时候,网络请求就开始了.当App Engine接收到请求时,它会 ...
- java 运行时环境和编译器环境
必须要保证运行环境高于编译环境 1.编译器的环境设置 单击项目右键-> Properties -> Java Compiler -> 5或6 如果编译器的环境高于运行时环境会报错. ...
- java 常用类库:操作系统System类,运行时环境Runtime
System类: System 类代表Java程序的运行平台,程序不能创建System类的对象, System类提供了一些类变量和类方法,允许直接通过 System 类来调用这些类变量和类方法. Sy ...
- iOS开发——高级特性&Runtime运行时特性详解
Runtime运行时特性详解 本文详细整理了 Cocoa 的 Runtime 系统的知识,它使得 Objective-C 如虎添翼,具备了灵活的动态特性,使这门古老的语言焕发生机.主要内容如下: 引言 ...
- Runtime运行时的那点事儿
注:本文是对 Colin Wheeler 的 Understanding the Objective-C Runtime 的翻译. 初学 Objective-C(以下简称ObjC) 的人很容易忽略一个 ...
- Java运行时环境---内存划分
背景:听说Java运行时环境的内存划分是挺进BAT的必经之路. 内存划分: Java程序内存的划分是交由JVM执行的,而不像C语言那样需要程序员自己买单(C语言需要程序员为每一个new操作去配对del ...
- ios - runtime运行时应用---交换方法
runtime运行时用法之一 --- 交换类的方法,此处简单写了把系统的UIView的setBackgroundColor的方法换成了自定义的pb_setBackgroundColor 首先创建UIV ...
- runtime 运行时机制 完全解读
runtime 运行时机制 完全解读 目录[-] import import 我们前面已经讲过一篇runtime 原理,现在这篇文章主要介绍的是runtime是什么以及怎么用!希望对读者有所帮助! ...
- Apache Flink 分布式运行时环境
Tasks and Operator Chains(任务及操作链) 在分布式环境下,Flink将操作的子任务链在一起组成一个任务,每一个任务在一个线程中执行.将操作链在一起是一个不错的优化:它减少了线 ...
随机推荐
- hdu1824 基础2sat
题意: Let's go home Time Limit: 10000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) ...
- 针对缓冲区保护技术(ASLR)的一次初探
0x01 前言 ASLR 是一种针对缓冲区溢出的安全保护技术,通过对堆.栈.共享库映射等线性区布局的随机化,通过增加攻击者预测目的地址的难度,防止攻击者直接定位攻击代码位置,达到阻止溢出攻击的目的的一 ...
- Windows核心编程笔记之进程
改变进程基址,获取进程基址 #include <Windows.h> #include <iostream> #include <strsafe.h> #inclu ...
- WindowsPE 第七章 资源表
资源表 在程序设计中,总会设计一些数据.这些数据可能是源代码内部需要用到的常量,菜单选项.界面描述等:也可能是源代码外部的,比如程序的图标文件.北京音乐文件.配置文件等,以上这些数据统称为资源.按照程 ...
- mac打开class文件
本来不想写这个东西的.但是这个却费了我一番周折. 我要先声明一点的是,我从来不讲iOS当成一个单独的系统,而是将这个操作系统归位unix内核的系统. 简单来说,我把它当成linux在用. 但是,mac ...
- Redis(附Win10版本 和可视化工具)
启动服务端 通过win+r,cmd 运行命令行然后输入如下指令: G: cd software cd G:\software\redis-64.3.0.503 redis-server.exe 这样就 ...
- 【实用小技巧】spring与springmvc自动扫描包重复的问题解决
spring对应配置文件为: <!-- 配置自动扫描的包,此时要排除Controller --> <context:component-scan base-package=" ...
- 基于RRCF(robust random cut forest)的时间序列异常检测流程
摘要:RRCF是亚马逊提出的一个流式异常检测算法,是对孤立森林的改进,可对时序或非时序数据进行异常检测.本文是我从事AIOps研发工作时所做的基于RRCF的时序异常检测方案. 1. 数据格式 ...
- ConcurrentHashMap源码解读三
今天首先讲解helpTransfer方法 final Node<K,V>[] helpTransfer(Node<K,V>[] tab, Node<K,V> f) ...
- 转: inline关键字使用
1.inline用在函数声明时,还是函数定义时?还是两边都加? 首先,内联函数声明和定义最好在同一个文件中,其它的情况没有实用上的意义. 只要在同一个文件中,声明和定义至少其一加"inlin ...