程序运行时的存储结构

编译原理 运行时的存储组织及管理 第七章 运行时的存储组织及管理 文章目录第七章 运行时的存储组织及管理7.1 概述7.2 静态存储分配7.3 动态存储分配7.3.1 活动记录7.3.2 建造display区的规则7.3.3 运行时的地址计算 7.1 概述 运行时的存储组织及管理是目标程序运行时所需要存储空间的组织与管理以及源程序中变量存储空间的分配。 静态存储分配 在编译阶段由编译程序实现对存储空间的管理,和为源程序中的变量分配存储的方法。 条件:如果在编译时能够确定源程序中变量在运行时的数据空间大小,且运行时不改变 但并不是所有数据空间 阅读详情

程序运行时的存储结构

目标程序在目标机器环境下运行时,只是在自己的运行时的存储空间内完成执行。通常,在有操作系统的情况下,程序在自己的逻辑存储空间内存储和运行。因此,编译程序在生成目标代码时应该明确程序的所有对象在逻辑存储空间是如何存储的,以及目标代码运行时是如何使用和分配自己的逻辑存储空间的。

–摘自《编译原理》第三版 王生原等编著。

注:本文中例子以c语言为例。

运行时存储组织

运行时存储组织的作用和任务

编译程序所产生的目标程序本身的大小通常是固定的,一般情况下放在代码区

目标程序所需要的数据对象放在数据区。这里的数据对象既包括用户定义的各种变量或者常量(比如:int a; 其中的a就是一个数据对象),也包括调用过程中所需的连接信息(比如:printf("hello world");,代码区也保存你调用的printf的函数的相关信息)。

数据对象的表示

明确源语言中各类数据对象在目标机器中的表示形式,其实就是确定具体的存储方案。

数据对象在目标机器中通常是以字节(Byte)为单位进行分配,同一类型的数据对象,在不同类型的目标机器字节数可能不同。

对于基本数据对象,比如说integer 通常占4个字节,character占一个字节,而指针类型的数据对象占一个单位字长(单位字长由目标机器位数决定)。

表达式计算

如何正确有效的组织表达式的计算,其中涉及到代码优化等问题。

存储分配策略

采取静态分配还是动态分配。静态分配(比如:c中打的static)是指编译时就确定数据对象的大小,个数。动态分配(比如c中的malloc或者c++和java中的new)是指运行时才能确定对象的存储分配。

过程实现

如何实现函数调用,参数传递,返回值等问题。

程序运行时存储空间的布局

粗略划分可以把程序的存储布局分为代码区和数据区,但是为了存储组织和管理,往往需要将它们划分为更加具体的区域。具体的划分因目标机器而定,但是一般来说,可以划分为以下几个部分:

  • 保留地址区。为操作系统保留的地址区域等。通常是不允许普通程序的读写,只允许操作系统的特权操作读写。
  • 代码区。静态存放编译产生的目标代码。
  • 静态数据区。静态存放全局数据。比如说用的全局变量以及静态变量等。
  • 共享库和分别编译模块。
  • 动态数据区。指的是动态变化的堆区和栈区。堆(数据对象由低地址–>高地址存储)。栈(数据对象由高地址–>低地址存储)。

这里写图片描述

栈式存储分配

采用栈来存储和管理。

在函数/过程的实现中,每次调用函数/过程时,就在当前栈顶加一个活动记录(activity record)。当函数执行完毕后,释放掉当前函数的栈顶记录。

这也是为什么会有变量的域概念这一说法,函数的局部变量,只在当前函数域内有效,执行完当前函数,就会释放掉当前函数域。

#include <stdio.h>
//计算两个数的加法
int sum(int a, int b)
{
    int c;
    c = a+b;

    return a+b;
}
int main(void)
{
    int a;
    int b;
    int c;
    c = sum(a,b);
    //打印计算结果
    printf("%d+%d = %d",a,b,c);

    return 1;
}

当执行上面的程序时:

  1. 程序从main函数开始执行
  2. 系统为main函数分配栈活动记录,将main函数的活动记录压进栈(push stack),当前栈顶指针指向main函数函数记录。
  3. 当函数执行到15行时,将开始调用sum函数
  4. 系统为sum函数分配栈活动记录,将sum函数的活动记录压进栈(push stack),当前栈顶指针指向sum函数活动记录。
  5. 执行完sum函数,将当前栈顶记录弹出(pop stack),当前栈顶指针指向main函数的活动记录。
  6. 将sum函数的返回值赋值给c。
  7. 函数数执行到17行时,调用系统I/O函数printf。
  8. 系统为printf函数分配栈活动记录,将printf函数的活动记录压进栈(push stack),当前栈顶指针指向printf函数的活动记录。
  9. 执行完printf函数,将当前栈顶记录弹出(pop stack),当前栈顶指针指向main函数的函数记录。
  10. 系统将main函数的活动记录弹出,程序执行完毕。
什么情况下才能该用栈式存储?

在编译时期,过程/函数以及嵌套程序块的活动记录大小(最大值)是可以确定的。

堆式存储分配

从栈式存储中,我们知道,每次函数执行完毕后,都会将当前栈顶活动记录弹出,这意味着变量随着函数执行的结束而丢失。但是有时候我们想要函数结束完之后,当前数据对象长期存在,这时候就该堆发挥作用了。

在堆式存储分配时,程序可以在任意时刻,以任意次序从程序的代码区的堆区申请和释放一个数据对象。通常情况下,堆的分配和释放是由程序向操作系统提出的,这也注定了它的分配效率没有栈那么快。

堆的分配和释放有两种方式:隐式(implicit)和显式(explicit)。

在c语言中没有显式的分配和释放堆的语句,但是可以用标准库中的malloc函数和free函数实现,这需要程序员的水平比较高。在java语言中,堆的释放都是有Java的垃圾回收器来隐式释放的而且这个垃圾回收器相当’聪明‘这也降低了java的入门门槛。

Cache学习(1):常见的程序运行模型&多级Cache存储结构 程序是运行在主存之中。当需要运行一个进程的时候,首先会从磁盘设备中将可执行程序load到主存中,然后开始执行。在CPU内部存在一堆的通用寄存器(register)。其实现实中,CPU通用寄存器的读写速度和主存之间存在着太大的差异。两者速度差异近百倍。当CPU试图从主存中load/store 操作时,由于主存的速度限制,CPU不得不等待这漫长的65ns时间,所以,上面举例的3个步骤中,步骤1和步骤3实际上速度很慢。如果可以提升主存的速度,那么系统将会获得很大的性能提升。 阅读详情

相关推荐

OC8051内部逻辑分析(1)

采用数据流的方式进行OC8051内部的逻辑分析,需要首先理解其存储器架构,然后追踪程序到再到数据流。   前面有提到过,OC8051程序和数据存储器逻辑分离,在物理上,其可能有4种存储器,分别为内部程序存储器irom,内部数据存储器iram,外部程序存储器器xrom,外部数据程序存储器xram,其中访问xram和访问iram的指令不同(mov、movx,并要通过DPTR寄存器)。OC8051使用

lkiller_hust的专栏 1537

编译原理--运行时存储组织(自己看)

1、 存储分配的基本概念 1、过程:函数和过程的程序单员 2、过程的活动:程序的一次执行 3、活动记录:一块连续的存储空间,存储过程活动的执行代码和所需信息。 名字、环境、状态、存储单元、值的关系 解释: 活动记录 有如下区域: 1、返回值区域:存放被调用过程的返回值,通常存放于寄存器以提高效率。 2、 实在参数区域(参数区域):存放被调用过程的参数。 3、控制链区域:指定调用者的活动记录地址,相当于指向活动记录的指针。用于返回上一个调用对象活动记录中。 4、机器状态区域:存储寄存器、程序计数

CodeEggs的博客 1294

ASF-YOLO:一种基于注意尺度序列融合的细胞实例分割YOLO模型

随着样本制备技术和显微成像技术的快速发展,细胞图像的定量处理和分析在医学、细胞生物学等领域发挥着重要作用。基于卷积神经网络(CNN),可以通过神经网络训练学习不同细胞图像的特征信息,具有很强的泛化性能。两阶段的R-CNN系列[1,2,3]及其一阶段变体[4,5]是实例分割任务的经典CNN基础框架。在最近的研究中,You Only Look Once(YOLO)系列[6,7,8,9]已经成为实时实例分割中速度最快、最准确的模型之一。

m0_47867638的博客 9808

【编译原理】8—运行时刻环境Runtime Environments(存储组织、栈式分配和非局部数据访问)

编译原理龙书第七章,运行时刻环境 Runtime Environments,详细介绍了存储组织、空间的栈式分配和数据访问原理

一棵灬大树的博客 2221

YOLOv5s模型训练全流程解析:从数据准备到实战检测

本文详细解析了YOLOv5s模型训练的全流程,涵盖从环境搭建、数据准备与格式转换,到模型训练、参数调优及实战检测的完整步骤。文章提供了具体的代码示例和常见问题解决方案,旨在帮助开发者,特别是新手,高效掌握YOLOv5s模型训练的核心技术,并成功应用于实际检测任务中。

weixin_29041767的博客 335

百度API实现人流量数量检测(动态)

百度的这个API还挺好用的,对与不追求高精度的人来说非常适用,结合他官方给的文档,极易上手。 需要做的就是通过API Key和Secret Key获取的access_token。 然后稍微修改下代码就行,但是他给的代码并没有直接从摄像头获取视频,而是读取一个文件夹,那么就需要自己先对摄像头的输出视频进行处理。 识别结果如下,"person_num"是当前画面的人数,in是累计进入的人数,out是累计走出去的人数。 他这个有个缺点就是返回值里边并没有实时返回in和out的值,而是都是0,但是这个图片上有,图片

qq_42479987的博客 3385

编译原理运行时刻环境

编译原理运行时刻环境 运行时存储组织概述 编译程序是将源程序的算法描述部分和数据说明部分,分别翻译成机器目标代码和数据存储单元,最终获得目标程序。 目标程序在目标机环境中运行时,都置身于自己的一个运行时存储空间。在基于操作系统之上运行的情况下,目标程序将在自己的逻辑地址空间内运行并存储数据。编译程序在生成代码时,负责明确各类对象在逻辑地址空间是如何存放的,以及目标代码运行时,如何使用逻辑地址空间。 在编译过程中,源程序的对象地址分配往往是相对于运行存储空间的偏移量,对象访问采用“基地址+偏移量”寻址方式进行

u010523811的博客 1923

EPICS pythonSoftIOC教程

EPICS pythonSoftIOC教程

yuyuyuliang00的博客 1522

编译原理第八章 运行时的存储组织与管理

概述 几乎所有的程序设计语言都使用如下三种类型的存储环境: 完全静态环境、基于栈的存储环境和基于堆的存储环境的一种或几种。 静态存储分配 最简单的运行时的环境类型是所有的数据都是静态的。如果在编译时就能确定目标程序运行中所需要的全部数据空间的大小,则编译时就能安排好目标程序的全部数据空间。 栈式存储分配 在运行递归调用且每次调用都要重新分配局部变量的语言中,需要使用栈式存储分配,其分配策略:将整个...

qq_42672030的博客 711

CentOS7下用FreeRADIUS+AD实现802.1X认证完整指南(附华为交换机配置)

本文提供了在CentOS 7系统上部署FreeRADIUS并与Windows Active Directory集成,以实现企业级802.1X网络认证的完整实战指南。内容涵盖从架构原理、服务器配置(包括Kerberos、Samba Winbind集成)、FreeRADIUS核心设置与AD联动,到华为交换机的详细配置步骤。重点解决了生产环境中常见的高可用、动态VLAN下发及深度排错问题,为企业构建集中、安全的网络准入控制体系提供了经过验证的解决方案。

weixin_29273849的博客 407

Mac上Ollama服务IP访问失败的3种修复方法(含永久生效配置)

本文详细介绍了Mac上Ollama服务IP访问失败的3种修复方法,包括临时环境变量覆盖、永久Shell配置修改及进阶排查技巧。重点解析了OLLAMA_HOST环境变量的配置原理,帮助开发者解决Connection refused问题,实现局域网IP访问Ollama服务的需求。

weixin_29209805的博客 210

Linux内存之Cache

一、 Linux内存之Cache 1.1、Cache的基本介绍 Cache存储器,是位于CPU和主存储器DRAM之间的一块高速缓冲存储器,规模较小,但是速度很快,通常由SRAM(静态存储器)组成。 Cache的功能是提高CPU数据输入输出的速率。Cache容量小但速度快,内存速度较低但容量大,通过优化调度算法,可以让系统的性能大大改善,感觉就像是又有了主存储器的内存,又有了Cache的访问速度。 1.2、程序是如何运行的? 我们先思考一个问题:我们的程序是如何运行起来的? 我们应该知道,程序是运行在RAM之

wyttRain的博客 1万+

2017年电赛题目-自适应滤波器

电赛题目解析之自适应滤波器 首先来看看题目: 2017全国大学生电子设计竞赛题目 这道题有很多发挥空间,本文将介绍三种电路: 数字电位器移相模拟电路 压控移相模拟电路 数字方法 一、数字电位器移相模拟电路 对于前级的加法器比较简单,这里贴出一种使用OPA209实现的常规做法: 输入端分别输入A信号和B信号就可以实现A+B,因为信号频率很低不涉及到阻抗匹配问题,所以这种接法没............

电气小能手的博客 2万+

进程是如何使用内存的?

(转自本人公众号) 程序运行概述 程序(我们这里只讨论单进程情况,存在多进程的程序如淘宝微信等不展开讨论)镜像存在磁盘中,运行时将镜像加载至内存RAM中,然后开始执行。 先来看一下CPU的多级存储结构,CPU通用寄存器访问速度最快,其次是Cache,再次是内存,磁盘访问速度最慢。 CPU的多级存储结构 对于进程而言,可使用的地址空间为2^32=4G,那么对于只有2G内存甚至只有256...

机械猿的博客 771

区块链技术与应用 【全国职业院校技能大赛国赛题目解析】Caliper从0到使用

技能大赛样题解析,caliper题目从0到使用

weixin_52865146的博客 2081

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

鸿蒙5.0开发【HAP依赖HAR A,HAR A依赖HAR B,HAP能否调用HAR B提供的接口?如果不支持间接依赖HAR,这么设计的原因是什么?】应用运维

而B和C的版本是不可控的,如果C的开发者发布了一个2.0.0的版本,下次安装依赖时,可能会安装C的2.0.0的版本。然后就有可能出现一些问题,例如:在代码没有任何改动的情况下,程序运行却出现报错,不同时间不同PC上构建的应用运行表现不一致等。间接依赖的版本是不可控的,如果代码里使用到某个版本的间接依赖,不同时间安装的依赖可能版本不一致,程序运行可能出现意想不到的错误。所以ohpm为了解决幽灵依赖的问题,设计了一个特殊的存储结构,从技术上进行限制、不允许引用间接依赖,从而避免出现幽灵依赖问题。

鸿蒙的技术博客 458

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

day16 数据结构

本文介绍了数据结构的基本概念和分类。数据结构是程序运行时临时存储和处理数据的容器,包含数据保存和处理功能(增删改查)。数据由数据项(最小单位)组成数据元素(基本单位),再构成数据对象(元素集合)。数据结构分为逻辑结构(集合、线性、树形、图形)和存储结构(顺序、链式、索引、散列),其中逻辑结构描述元素间关系,存储结构则实现逻辑结构在物理内存上的映射。

饿了 334

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

hashCode笔记---------------------------------

hashCode()方法的作用 1、查找的快捷性,hashCode用来在散列存储结构中确定对象的存储地址。2、配合散列集合的正常运行,如HashSet、HashMap、HashTable,提高程序运行效率。 * 当一个集合中已经有大量的数据,向集合中放入数据时,如果采用equals方法逐一比较,效率会特别低,这时 * hashCode方法起到了作用,在存入对象时,首先计算出hashCode值

停住了过去,却停不住时间 266

[C#]基本概念:堆栈

简单来说: 堆: 1. 存放类型:引用类型变量(即需要new操作符分配内存的变量)2. 内存管理方式:属于非托管内存管理区域,变量使用之前需要new操作符手工分配内存,使用完毕需要手工释放占用内存。3. 存储结构:堆型散列 栈: 1. 存放类型:用于存放值类型变量(即不需要new操作符分配内存的变量)2. 内存管理方式:内存由.net平台统一管理,即托管内存区域,变量生命周

lemong的专栏 993

【从零到一】实现C++语言编译器(6)

代码生成

喵 463

堆栈的栈顶和栈底在哪_什么是堆栈

公众号:汽车ECU开发​对于堆栈的概念,一直不太了解,那么究竟什么是堆, 什么又是栈呢?接下来, 我们就来看看它们各自的概念 。栈, 是硬件, 主要作用表现为一种数据结构, 是只能在一端插入和删除数据的特殊线性表。允许进行插入和删除操作的一端称为栈顶, 另一端为栈底。栈按照后进先出的原则存储数据, 最先进入的数据被压入栈底, 最后进入的数据在栈顶, 需要读数据时从栈顶开始弹出数据。栈底固定, 而栈...

weixin_39693295的博客 5593

c++链表

c++链表

2301_76461941的博客 1102

注解解析的底层实现

通过 @Retention 元注解可以控制注解的保留策略,当使用 RetentionPolicy.RUNTIME 时,可以在运行时通过反射 API 来解析注解信息。在 JVM 层面,会从字节码文件中读取注解信息,并创建注解的代理对象来获取注解的属性值。2、底层原理:反射机制的核心类是 java.lang.reflect.AnnotatedElement,它是所有可以被注解修饰的元素(如 Class、Method、Field 等)的父接口。注解的解析主要依赖于 Java 的反射机制。

qq_74475840的博客 251

计算机存储结构分析

计算机存储结构分析图注:此图及其重要,它可以帮你很清晰的理解程序数据执行的流程,以及CPU的调度机制。一、寄存器寄存器:是中央处理器(CPU)中的一部分,有限存贮容量的高速存贮部件(空间比较小在kb级别),用来暂存指令、数据和地址。CPU对内存中的数据进行处理时,往往先把数据取到寄存器中,而后再作处理,加快直接同内存读取指令和读写数据的速度。二、高速缓冲存储器高速缓冲存储器:是存在于内存与CPU之间

的博客 5050

JVM内存结构 VS Java内存模型 VS Java对象模型

Java作为一种面向对象的,跨平台语言,其对象、内存等一直是比较难的知识点。而且很多概念的名称看起来又那么相似,很多人会傻傻分不清楚。比如本文我们要讨论的JVM内存结构、Java内存模型和Java对象模型,这就是三个截然不同的概念,但是很多人容易弄混。 可以这样说,很多高级开发甚至都搞不不清楚JVM内存结构、Java内存模型和Java对象模型这三者的概念及其间的区别。甚至我见过有些面...

richer__的博客 127

数据的存储结构

就已经确定了数组的大小,而动态数组则可以。

OrPeel的博客 7442
上一篇: Ethernet
下一篇: Linux的磁盘和文件系统
Coder_Stephen
博客等级 码龄9年 16粉丝 23原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值