什么是内存中的堆和栈?与数据结构中的堆和栈有什么区别?

内存中的堆和栈

一直使用堆和栈的相关概念,对内存中(操作系统)中的堆与栈和数据结构中的堆与栈一直不求甚解,这次,突然想起这个问题,在此进行一个简单梳理归纳,如有错误,恳请读者指出。

栈(stack)

img

栈是由系统自动分配和回收的内存。例如,编写一个简单的C++程序,main函数内依次调用两个全局函数1、2,压栈顺序大体按照 main函数入栈-> 调用的函数1入栈-> 调用的函数2入栈出栈顺序与入栈相反 可参考 函数压栈的过程

栈区位于内存较高的地址,由最高内存地址向低地址扩展(即Push压栈时栈顶指针从最高内存地址向下移动

栈是一个先进后出(FILO)结构。把数据压入栈时用push进入;当从栈取出数据时用pop取出。栈随着数据被压入或者弹出而增长或者减小。最新压入栈的项被认为是在“栈的顶部”。当从栈中弹出一个项时,我们得到的是位于栈最顶部的那一个(即最新压入的那一个)

在x86体系中,栈顶由堆栈指针寄存器ESP来标记,它是一个32位寄存器,里面存放着最后一个压入栈顶的项的内存地址。正因为有它,我们才能够随时操作到需要的项。需要注意的是,栈顶是朝着地内存方向增长的。

ESP:栈指针寄存器(extended stack pointer),其内存放着一个指针,该指针永远指向系统栈最上面一个栈帧的栈

EBP:基址指针寄存器(extended base pointer),其内存放着一个指针,该指针永远指向系统栈最上面一个栈顶的底部。

在 WINDOWS下,栈的大小是2M(也有的说是1M,总之是一个编译时就确定的常数),如果申请的空间超过栈的剩余空间时,将提示overflow。因此,能从栈获得的空间较小

堆(heap)

堆区是向上增长的用于分配程序员申请的内存空间。

操作系统有一个记录空闲内存地址的链表(当然也有可能用位图等其他方法,这里假设使用链表),当系统受到程序的申请时,会遍历该链表,寻找第一个空间大于所申请空间的堆(假设使用首次适应(FirstFit)算法)。然后将该结点从空闲结点链表中删除,并将该结点的空间分配给程序, 另外,对于大多数系统,会在这块内存空间中的首地址处记录本次分配的大小,这样,代码中的delete语句才能正确的释放本内存空间。 由于找到的堆结点的大小不一定正好等于申请的大小,系统会自动的将多余的那部分重新放入空闲链表中。 也就是说堆会在申请后还要做一些后续的工作这就会引出申请效率的问题。

img

二者分别存储什么以及原因

栈:就是那些由编译器在需要的时候分配,在不需要的时候自动清除的变量的存储区。里面的变量通常是局部变量、函数参数等。

可以看到栈有一个ESP寄存器管理,从底层就实现了一种“自动化”,而堆似乎并没有额外的东西来帮助管理。

此外,栈的大小需要有一定的限制,栈的增长是向低地址扩展,如照片中看到的,如果栈不断地增加,很可能会与**.bss段**发生碰撞,这是不堪设想的,系统会发出错误并终止程序。

栈应该被看成一个短期存储数据的地方,存在在栈中的数据项没有名字,只是按照后进先出来操作罢了。

栈经常可以用来在寄存器紧张的情况下,临时存储一些数据,并且十分安全。

当寄存器空闲后,我们可以从栈中弹出该数据,供寄存器使用。这种临时存放数据的特性,使得它经常用来存储局部变量,函数参数,上下文环境等。

栈是机器系统提供的数据结构,计算机会在底层对栈提供支持:分配专门的寄存器存放栈的地址,压栈出栈都有专门的指令执行,这就决定了栈的效率比较高

相反,堆相对于栈,更加强调需要进行控制。常见的就是我们手动申请,手动释放。因此可以分配更大的空间,但开销也会更多。 因此

堆是在程序执行的过程中动态分配的,它最大的特性就是动态性。堆就是那些由new分配的内存块,他们的释放编译器不去管,由我们的应用程序去控制,一般一个new就要对应一个delete。如果程序员没有释放掉,那么在程序结束后,操作系统会自动回收。

其他存储区

(3)静态存储区:所有的静态对象,全局对象都于静态存储区分配。

(4)常量存储区:这是一块比较特殊的存储区,他们里面存放的是常量,不允许修改。常量字符串都存放在静态存储区,返回的是常量字符串的首地址。

示例代码


   int a = 0;  全局初始化区

   char *p1;  全局未初始化区

   int main ()

   {

   int b;char  s[] = “abc”;char *p2;char *p3 =123456; 123456\0 在常量区,p3 在栈区

   static  int c = 0; 全局(静态)初始化区

   p1 = (char *)malloc(10);堆

   p2 = (char *)malloc (20);}

栈和堆的比较

项目
申请效率效率高,由系统分配,程序员无法控制效率低,程序员通过new分配,速度较慢,容易产生内部碎片
申请大小最大容量一般由系统预先设定,例如2M堆获得的空间较大,较灵活。向高地址扩展,不连续的内存区域(例如用链表存储空闲内存地址)
存储内容在函数调用时,第一个进栈的是主函数中函数调用后的下一条指令(函数调用语句的下一条可执行语句)的地址,然后是函数的各个参数,在大多数的C编译器中,参数是由右往左入栈的,然后是函数中的局部变量。注意静态变量是不入栈的。
当本次函数调用结束后,局部变量先出栈,然后是参数,最后栈顶指针指向最开始存的地址,也就是主函数中的下一条指令,程序由该点继续运行。
一般是在堆的头部用一个字节存放堆的大小。堆中的具体内容有程序员安排。
存取效率char s1[] = "运行时赋值";
放入栈中,是运行时赋值
char *s2 = "编译时确定";放入堆中,编译时就确定。(堆中是存储对象的,而在栈中是存放引用)

深入阅读

参考资料: 内存中的堆和栈到底是什么

数据结构中的堆和栈

一种先进后出的数据结构,栈(stack)又名堆栈,它是一种运算受限的线性表。限定仅在表尾进行插入和删除操作的线性表。这一端被称为栈顶,相对地,把另一端称为栈底。向一个栈插入新元素又称作进栈、入栈或压栈,它是把新元素放到栈顶元素的上面,使之成为新的栈顶元素;从一个栈删除元素又称作出栈或退栈,它是把栈顶元素删除掉,使其相邻的元素成为新的栈顶元素。

通常是一个可以被看做一棵树的数组对象。堆总是满足下列性质:

  • 堆中某个结点的值总是不大于或不小于其父结点的值;
  • 堆总是一棵完全二叉树。

完全二叉树:若设二叉树的深度为k,除第 k 层外,其它各层 (1~k-1) 的结点数都达到最大个数,第k 层所有的结点都连续集中在最左边,这就是完全二叉树。 (即未满的层只能是最后一层,且节点均连续集中在最左边)

兰缕启林
关注 关注
  • 13
    点赞
  • 64
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
数据结构以及内存
weixin_44548640的博客
03-31 1481
全局变量在所有函数外定义,作用于全局域,在其他文件使用的时候需要使用extern关键字声明。 局部变量具有局部作用域,在函数执行时存在,函数执行结束即注销。 静态局部变量,初始化一次,然后一直存在到程序结束,但是只对定义自己的函数体可见。 静态全局变量,作用于全局域,如果有多个文件,只能作用域一个文件,如果有两个源文件定义同一个名字的静态全局变量,不会发生冲突。 ...
java面试 数据结构内存区别
weixin_44026997的博客
02-19 1335
(heap)和(stack)的区别 1、存储 :变量、对象的引用 :实例对象 2、速度 :存取速度快 :存取速度慢 3、线程访问 :每个线程都有一个:所有线程共享一个区 4、垃圾回收 :比较频繁 :不频繁 详情: 内存:内存首先是一片内存区域,存储的都是局部变量,凡是定义在方法的都是局部变量(方法外的是全局变量),for循环内部定义的也是局部变量,是先加载函数才能...
内存区别
04-05
简单的介绍内存区别。个人觉得还不错的。
(每日一问)基础知识:区别
最新发布
upgrador的博客
08-29 1481
在程序开发,理解(Heap)和(Stack)这两种内存分配方式对于写出高效的代码至关重要。本文将通过实例代码、概述、对比分析以及图表展示的方式,深入探讨区别,帮助读者更好地掌握这一基础知识。
内存
truddysnow的专栏
03-24 1292
程序用来存放数据的内存分为四块,其实另有一块用于存放代码,这里我们不讨论,这四块分别是: 1、全局区(静态区)(static):全局变量和静态变量都存储在这块区域,与其他变量的明显区别就是生命周期不同,在程序结束时,系统会释放这块资源 2、文字常量区 :常量字符串就是放在这块区域,即是我们常说起的常量池。这块也是在程序结束时由系统释放。 3、区(stack):存放函数的参数值,局部变量的值等。
内存区别
枕上听潮
07-17 508
内存区别 原文: http://student.csdn.net/link.php?url=http://www.top-e.org%2Fjiaoshi%2Fhtml%2F427.html 在计算机领域,是一个不容忽视的概念,我们编写的C语言程序基本上都要用到。但对于很多的初学着来说,是一个很模糊的概念。 :一种数据结构、一个在程序运行时用于存
内存里面的
weixin_50956409的博客
07-10 203
都是内存数据结构,但它们在内存的实现和用途有所不同。通常用于存储函数调用相关的数据,而则用于存储动态分配的数据。的大小固定,由编译器或操作系统管理;而的大小可以根据需要动态变化,由程序员手动管理。正确地使用可以提高程序的性能和内存使用效率。
JVM内存内存区别
08-31
因此,理解内存管理机制对于编写高效、无内存问题的Java程序至关重要。 在内存分配策略上,静态存储分配通常在编译时完成,适合静态数据结构式存储分配在函数调用时进行,适用于局部变量和固定大小的...
java 内存内存理解
08-31
了解内存的工作原理对于优化Java程序的性能和管理内存资源至关重要。开发者应当合理地利用的优势,避免不必要的内存消耗,提高程序的运行效率。在编写Java代码时,理解何时在声明变量,何时在...
内存数据结构有什么区别
03-31
内存数据结构有以下区别: 1. 内存是指内存空间的两个不同的存储区域,而数据结构是指两种不同的数据结构。 2. 内存是由编译器自动分配和释放,存储局部变量、...
简述JAVA内存内存区别
08-18
允许程序在运行时动态地申请某个大小的内存空间,内存实际上指的就是(满足内存性质的)优先队列的一种数据结构,第1个元素有最高的优先权。 内存的大小受限于计算机系统有效的虚拟内存。由此可见,...
内存
如果可以我想再爱一次的博客
02-15 161
内存 的理论知识 申请方式 stack:是由系统自动分配的,例如,声明在函数的一个局部变量 int b;系统自动在为b开辟空间 heap:需要程序员手动申请,并指明大小, 在C的malloc函数 如:char* p1 = (char*)malloc(sizeof(char)); 在C++的new运算符 如:int *p2 = new int[100] p1和p2本身就是在的 申请后系统的响应 :只要的剩余空间大于所申请的空间,系统将为程序自动提供内存,否则将报异常提
内存
编码人生
11-12 300
一般认为在c分为这几个存储区  1. - 有编译器自动分配释放 ; 2. - 一般由程序员分配释放,若程序员不释放,程序结束时可能由OS回收 ; 3.全局区(静态区),全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块 区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域; -> 程序结束释放  4.另外还有一个专门放常量的地方; - >程序结束释放...
内存是什么
yesman317的专栏
03-10 187
要点: :顺序随意 :先进后出 区别 一、预备知识—程序的内存分配 一个由c/C++编译的程序占用的内存分为以下几个部分 1、区(stack)— 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构。 2、区(heap) — 一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 。注意...
内存内存
z2431435的博客
06-19 188
在函数定义的一些**基本类型的变量**和**对象的引用变量**(变量名)都在函数的**内存分配**。 当在一段代码块**定义一个变量**时,Java就**在为这个变量分配内存空间**,**超过变量的作用域**,Java会**自动释放**掉为该**变量所分配的内存空间**,该**内存空间可以立即被另作他用**。 **内存用来存放由new创建的对象**(包括由基本类型包装起来的类:Integer、String、Double,实际上每个基本类型都有他的包装类)和**数组**。......
写文章

热门文章

  • 一文带你读懂深度学习中的张量(tensor)是什么,它的运算是怎样的,如何理解张量,张量的维度,浅显易懂 22528
  • python中json操作(json.loads json.load json.jumps json.jump 用法总结) 10000
  • mybatis添加空值 向数据库中添加null 7634
  • linux安装SSH与启动SSH服务 linux服务器如何通过SSH远程访问 7513
  • mybatis设置主键自增,报错: No setter found for the keyProperty 6812

分类专栏

  • 服务器 3篇
  • 深度学习 3篇
  • nas 1篇
  • Python学习 5篇
  • linux 2篇
  • Java学习 6篇
  • 笔记 2篇
  • mybatis 2篇
  • elasticsearch 2篇
  • Spring 1篇
  • python问题解决 2篇
  • HTML 1篇
  • 前端学习 1篇
  • json 1篇
  • docker 1篇

最新评论

  • 一文带你读懂深度学习中的张量(tensor)是什么,它的运算是怎样的,如何理解张量,张量的维度,浅显易懂

    caicaizitt: 通俗易懂

  • C++不是类的成员未知重写说明符已经定义或声明成员函数没有重载函数可以接受跳过明显的函数体意外的标记位于前的问题解决

    CSDN-Ada助手: 多亏了你这篇博客, 解决了问题: https://ask.csdn.net/questions/8017292, 请多输出高质量博客, 帮助更多的人

  • SSH能够连接但SFTP不能连接 sftp-server不存在 sftp-server安装

    jielsens: 不明白为什么得取消这个注释mac才能连,但windows电脑可以不需要就能连接sftp

  • [Java初学]Java上溯造型(upcasting)与下溯造型(Downcasting)

    Payton660: 个人认为,这个赋值,就是upcasting和downcasting这种东西,可以用“潜力”这个东西来解释。 在创建对象的时候,就已经定义了对象的“能力范围",如果定义的类型为父类,那么就限制了能力的发挥,但是他可以通过向下来解除能力的限制。

  • 一文带你读懂深度学习中的张量(tensor)是什么,它的运算是怎样的,如何理解张量,张量的维度,浅显易懂

    慕梅^: 博主讲的真是好

最新文章

  • frp内网穿透 web服务 proxy [proxies]: subdomain and custom domains should not be both empty. 无域名如何配置?
  • 语言模型中ptb数据集处理方法 讲解darts中rnn部分数据处理方法解读
  • SSH能够连接但SFTP不能连接 sftp-server不存在 sftp-server安装
2024年1篇
2023年2篇
2022年4篇
2021年22篇
2020年2篇

目录

目录

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值

玻璃钢生产厂家山东周年庆典商场美陈生产厂家扬州春季商场美陈九江广场玻璃钢雕塑报价福建秋季商场美陈供货商北京商场主题创意商业美陈怎么样门市玻璃钢花盆上海超市商场美陈销售公司海口做玻璃钢雕塑的昆明市玻璃钢雕塑设计多少钱安徽玻璃钢伟人雕塑北京户内玻璃钢雕塑生产厂家宜宾玻璃钢海豚雕塑定制河北工业玻璃钢雕塑规格尺寸曲阳玻璃钢卡通雕塑厂家广东户外玻璃钢雕塑定制河北景观玻璃钢雕塑性价比高的玻璃钢卡通雕塑宣城玻璃钢雕塑厂北关玻璃钢花盆花器浦东玻璃钢动物雕塑太原景区玻璃钢雕塑安装保山玻璃钢座椅雕塑报价洛阳哪里有卖玻璃钢雕塑铜梁玻璃钢花盆厂家芙蓉玻璃钢花盆花器艺术玻璃钢雕塑工程酒瓶玻璃钢雕塑工厂供应好的玻璃钢人物雕塑玻璃钢雕塑源茂吉县商场美陈香港通过《维护国家安全条例》两大学生合买彩票中奖一人不认账让美丽中国“从细节出发”19岁小伙救下5人后溺亡 多方发声单亲妈妈陷入热恋 14岁儿子报警汪小菲曝离婚始末遭遇山火的松茸之乡雅江山火三名扑火人员牺牲系谣言何赛飞追着代拍打萧美琴窜访捷克 外交部回应卫健委通报少年有偿捐血浆16次猝死手机成瘾是影响睡眠质量重要因素高校汽车撞人致3死16伤 司机系学生315晚会后胖东来又人满为患了小米汽车超级工厂正式揭幕中国拥有亿元资产的家庭达13.3万户周杰伦一审败诉网易男孩8年未见母亲被告知被遗忘许家印被限制高消费饲养员用铁锨驱打大熊猫被辞退男子被猫抓伤后确诊“猫抓病”特朗普无法缴纳4.54亿美元罚金倪萍分享减重40斤方法联合利华开始重组张家界的山上“长”满了韩国人?张立群任西安交通大学校长杨倩无缘巴黎奥运“重生之我在北大当嫡校长”黑马情侣提车了专访95后高颜值猪保姆考生莫言也上北大硕士复试名单了网友洛杉矶偶遇贾玲专家建议不必谈骨泥色变沉迷短剧的人就像掉进了杀猪盘奥巴马现身唐宁街 黑色着装引猜测七年后宇文玥被薅头发捞上岸事业单位女子向同事水杯投不明物质凯特王妃现身!外出购物视频曝光河南驻马店通报西平中学跳楼事件王树国卸任西安交大校长 师生送别恒大被罚41.75亿到底怎么缴男子被流浪猫绊倒 投喂者赔24万房客欠租失踪 房东直发愁西双版纳热带植物园回应蜉蝣大爆发钱人豪晒法院裁定实锤抄袭外国人感慨凌晨的中国很安全胖东来员工每周单休无小长假白宫:哈马斯三号人物被杀测试车高速逃费 小米:已补缴老人退休金被冒领16年 金额超20万

玻璃钢生产厂家 XML地图 TXT地图 虚拟主机 SEO 网站制作 网站优化