首页 > 系统相关 >内存堆栈结构

内存堆栈结构

时间:2023-12-13 20:59:26浏览次数:30  
标签:变量 对象 类型 内存 页表 堆栈 结构 指针

参考:

秒懂 栈内存和堆内存(深入底层) (xjx100.cn)

堆栈与堆(Stack vs Heap):有什么区别?图文并茂拆解代码解析! - 知乎 (zhihu.com)

学习CLR via C#(二) - 类型基础-CSDN博客

我们都知道值类型存在“栈”中,引用类型存在“堆”中。这篇文章深入讨论下内存的栈和堆的结构。

1.前言

1.指针

人们通常把“内存地址”形象的称作“指针”。栈内存和堆内存都是通过指针找到值(基本数据、对象、函数体等内容)。CPU为了管理内存而建立的虚拟地址空间指针页表,map或表结构),将虚拟地址映射到物理地址。

指针页表:指针变量(后面会提到)到物理地址的映射。 管理内存的Map表由操作系统按一定规则创建,不同的应用程序管理自己独占的内存空间。

2.变量

变量是栈内存指针的别名

声明变量是在指针页表里建立变量信息。而赋值才是真正的开辟内存空间。但是为了节省内存,会现在内存中查找有没有相同的值(栈的内存共享),如果有就把找到的内存地址更新到对应的map页表中,如果没有才会开辟内存空间。

所以变量名与值数据是分开存放的。保存变量名的内存地址称为指针变量

我们读取或修改变量就是CPU和内存等计算机硬件根据“执行上下文”对内存进行寻址和修改的过程。

3.垃圾回收

当变量赋值为null时,也就是将指针页表中的值地址指向null,表示该变量可以被释放。是否释放或销毁该变量,需要看作用域中是否有其他地方引用了该变量。

垃圾回收机制每隔一段时间自动扫描指针页表,检索所有变量,判断被引用的次数,同时在作用域树上查找是否引用了该变量。如果引用标记次数为0,或者通过扫描未找到变量的引用。那该变量就会被释放,即从指针页表中删除。

4.内存溢出

内存溢出是指程序在申请内存的时候,没有足够的空间供其使用。比如内存用完了或者申请了一个int,但给他存了一个double才能存下的数

什么情况会导致这个:

1.栈帧过多导致栈内存溢出。一个函数内调用另一个函数,不断重复这个过程,每次调用都会分配一个栈帧,导致栈爆掉。

2.栈帧过大导致内存溢出,比如int去存double的值。

5.内存泄漏

内存泄露是指程序在申请内存后,无法释放已申请的内存空间,一次内存泄露危害可以忽略,但内存泄露堆积后果很严重,无论多少内存,迟早会被占光。比如,栈内存指向堆内存的地址丢失,导致无法及时回收。

2.内存分配

一般来说,内存可以分为以下几个部分:

1.全局段:存储全局变量和静态变量,这些变量的生命周期等于程序执行的整个持续时间。

2.代码段:包含组成我们程序的实际机器代码或指令,包括函数和方法。

3.堆栈段:用于管理局部变量、函数参数和控制信息(例如返回地址)

4.堆段:提供了一个灵活的区域来存储大型数据结构和具有生命周期的对象,堆内存可以在程序执行期间分配或释放

 2.栈内存(有序连续存储)

“栈”具有线程和“先进后出”的特点,也就是每个栈桢一般会保存下一个栈桢的地址,指向next节点(即指向下一个栈桢),从而手牵手形成类似队列的链式结构。同时先入栈的会先执行,后入栈的会先弹出(执行完销毁)。

特点:

1.数据一执行完毕,变量会立即释放,节约内存空间(函数运行完其申请的栈会全部释放(函数申请的栈是在总栈的最上面))

2.由于有序连续,存取速度快。

3.存在栈中的数据大小与生存期必须是确定的,缺乏灵活性。

 3.堆内存(无序不连续)

堆内存允许我们在程序执行期间随时分配和释放内存。它非常适合存储大刑数据结构或大小事先未知的对象。

特点:

1.堆内存大小可以在程序执行过程中发生变化

2.在堆中分配和释放内存速度较慢,因为它涉及寻找合适的内存帧和处理碎片

3.存储在堆内存中的数据将一直保留在那里,直到我们手动释放它或程序结束

4.语言没有自动管理的话,需要手动管理

4.函数调用(C#)

调用函数时会创建称为堆栈帧的内存块。堆栈帧存储与局部变量、参数和函数的返回地址相关的信息。该内存是在堆栈段上创建的。

例子:

internal class Employee {
    public               int32         GetYearsEmployed()       { ... }
    public    virtual    String        GenProgressReport()      { ... }
    public    static     Employee      Lookup(String name)      { ... }    
}
internal sealed class Manager : Employee { 
    public    override   String         GenProgressReport()    { ... }
}    

1.线程栈就是前面提到的栈帧,走到M3函数的时候建好线程栈。

2.当JIT编译器将M3的IL代码转换成本地CPU指令时,会注意到M3的内部引用的所有类型:Employee、Int32、Manager以及String(因为"Joe")。假设走进M3之前string和Int32已经创建了类型对象。这里只加载Employee和Manager

 

 

3.在线程栈分配局部变量,初始化为null或0

 4.在托管堆创建Manager对象实例,使其类型对象指针指向对应的类型对象,并调用该类的构造器。创建完成后将其在堆上的地址返回给e

 

 5.调用Employee的静态方法Lookup。调用一个静态方法时,CLR会定位到与定义静态方法的类型对应的类型对象。然后,JIT再在其方法表中找到方法并编译。构造一个新的Manager对象并将地址赋给e。这时原来的Manager会被GC回收掉

 6.调用非虚实例方法GetYearsEmployed。调用一个非虚实例方法时,JIT编译器会找到e对应的类型对象的方法并执行,如果没有找到,就依次回溯其类型对象的基类型的类型对象,之所以能这样回溯,是因为每个类型对象都有一个字段引用了他的基类型

 7.调用虚实例方法GenProgressReport。调用一个虚实例方法时(虚表todo)

8类型对象的类型对象指针是指向Type类型对象的。

 

 

标签:变量,对象,类型,内存,页表,堆栈,结构,指针
From: https://www.cnblogs.com/mcyushao/p/17899531.html

相关文章

  • 实验6 C语言结构体、枚举应用编程
    1.实验任务1【验证性实验】2.实验任务2【验证性实验】3.实验任务3【验证性实验】4.实验任务4task4源代码:1#include<stdio.h>2#include<stdlib.h>3#defineN1045typedefstruct{6charisbn[20];//isbn号7charname[80];......
  • Redis数据结构4:REDIS_ZIPLIST
    REDIS_ZIPLISTzipList(压缩列表)是一种紧凑型的数据结构,占用一片连续的内存,本质上是一个字节数组。能提高CPU缓存的利用效率,并且针对不同数据结构进行不同编码,节省内存开销。编码结构zipList的字节数组主要由5个部分组成:zlbytes、zltail、zllen、zltail和entry。zlbytes记录......
  • 临床检验检查信息系统(LIS系统源码)C/S结构的应用模式
     LIS系统实现了实验室人力资源管理、标本管理、日常事务管理、网络管理、检验数据管理(采集、传输、处理、输出、发布)、报表管理过程的自动化,使实验室的操作人员和管理者从繁杂的手工劳作中解放出来,提高了检验人员的工作效率和效益,降低了劳动成本和差错发生率。LIS采用C/S(Clien......
  • 数据结构:双链表
    由于双链表中大部分操作其实和单链表操作类似,所以这里只挑关键的一些函数1、定义与初始化typedefstructDNode{ElementTypedata;structDNode*prior,*next;}DNode,*DLinkList;boolInitialDLinkList(DLinkList&L){L=(DNode*)malloc(sizeof(DNode));......
  • Asp.net core Net6.0 Webapi 项目如何优雅地使用内存缓存
    前言缓存是提升程序性能必不可少的方法,Asp.netcore支持多级缓存配置,主要有客户端缓存、服务器端缓存,内存缓存和分布式缓存等。其中客户端缓和服务器端缓存在使用上都有比较大的限制,而内存缓和分布式缓存则比较灵活。内存缓存就是一种把缓存数据放到应用程序内存中的机制。本......
  • windbg 内存
    1!address!address 扩展显示目标进程或目标机使用的内存信息。这个学习起来比较简单:我们直接使用!address-?就可以找到它的使用说明:给个例子:0:001>!address-?!address-printsinformationontheentireaddressspace!address-?-p......
  • DevEco Studio 鸿蒙(HarmonyOS)项目结构
    DevEcoStudio鸿蒙(HarmonyOS)项目结构一、操作环境操作系统: Windows10专业版IDE:DevEcoStudio3.1SDK:HarmonyOS3.1编辑二、项目结构创建简单的HelloWorld移动应用项目结构如下图编辑由上到下说明各个文件夹的作用.hvigor:存储构建配置文件信息。.idea:存储项目的配置信息。A......
  • 实验6 C语言结构体、枚举应用编程
    1.实验任务1源代码1//P286例8.172//对教材上的程序作了微调整,把输出学生信息单独编写成一个函数模块3//打印不及格学生信息和所有学生信息程分别调用45#include<stdio.h>6#include<string.h>7#defineN3//运行程序输入测试时,可......
  • simpread-Ubuntu 扩容磁盘、扩容内存_ubuntu 扩容 the file system can not be resize
    原文地址blog.csdn.net参考:Ubuntu磁盘扩容及启动问题整理作者:一只青木呀发布时间:2020-12-0810:42:19网址:https://blog.csdn.net/weixin_45309916/article/details/110850358也可参照正点原子的:Ubuntu磁盘空间不足?一招轻松扩容Ubuntu磁盘扩容(简单亲测有效)Ubuntu......
  • 有一个1G大小的一个文件,里面每一行是一个词,词的大小不超过16字节,内存限制大小是1M。返
    计算:所以我们要按照1M的上限来计算,假设每个单词都为16个字节,那么1M的内存可以处理多少个单词呢?1M=1024KB=1024*1024B。然后1M/16B=2^16个单词1G大概有多少个单词呢?有2^26个单词但是实际中远远不止这些,因为我们是按照最大单词长度算的。我们需要把这1G的单词分批处......