堆(Heap)与栈(Stack)是开发人员必须面对的两个概念,在理解这两个概念时,需要放到具体的场景下,因为不同场景下,堆与栈代表不同的含义。一般情况下,有两层含义:
(1)程序内存布局场景下,堆与栈表示的是两种内存管理方式;
(2)数据结构场景下,堆与栈表示两种常用的数据结构
1.程序内存分区中的堆与栈
栈由操作系统自动分配释放 ,用于存放函数的参数值、局部变量等,其操作方式类似于数据结构中的栈。参考如下代码:
其中函数中定义的局部变量按照先后定义的顺序依次压入栈中,也就是说相邻变量的地址之间不会存在其它变量。栈的内存地址生长方向与堆相反,由高到底,所以后定义的变量地址低于先定义的变量,比如上面代码中变量s的地址小于变量b的地址,p2地址小于s的地址。栈中存储的数据的生命周期随着函数的执行完成而结束。
2堆简介
堆由程序员分配释放, 若程序员不释放,程序结束时由OS回收,分配方式倒是类似于链表。参考如下代码:
其中p1所指的10字节的内存空间与p2所指的10字节内存空间都是存在于堆的。堆的内存地址生长方向与栈相反,由低到高,但需要注意的是,后申请的内存空间并不一定在先申请的内存空间的后面,即p2指向的地址并不一定大于p1所指向的内存地址,原因是先申请的内存空间一旦被释放,后申请的内存空间则会利用先前被释放的内存,从而导致先后分配的内存空间在地址上不存在先后关系。堆中存储的数据的若未释放,则其生命周期等同于程序的生命周期。
关于堆上内存空间的分配过程,首先应该知道操作系统有一个记录空闲内存地址的链表,当系统收到程序的申请时,会遍历该链表,寻找第一个空间大于所申请空间的堆节点,然后将该节点从空闲节点链表中删除,并将该节点的空间分配给程序。另外,对于大多数系统,会在这块内存空间中的首地址处记录本次分配的大小,这样,代码中的delete语句才能正确地释放本内存空间。由于找到的堆节点的大小不一定正好等于申请的大小,系统会自动的将多余的那部分重新放入空闲链表。
3堆与栈区别
堆与栈实际上是操作系统对进程占用的内存空间的两种管理方式,主要有如下几种区别:
(1)管理方式不同。栈由操作系统自动分配释放,无需我们手动控制;堆的申请和释放工作由程序员控制,容易产生内存泄漏;
(2)空间大小不同。每个进程拥有的栈的大小要远远小于堆的大小。理论上,程序员可申请的堆大小为虚拟内存的大小,进程栈的大小64bits的Windows默认1MB,64bits的Linux默认10MB;
(3)生长方向不同。堆的生长方向向上,内存地址由低到高;栈的生长方向向下,内存地址由高到低。
(4)分配方式不同。堆都是动态分配的,没有静态分配的堆。栈有2种分配方式:静态分配和动态分配。静态分配是由操作系统完成的,比如局部变量的分配。动态分配由alloca函数进行分配,但是栈的动态分配和堆是不同的,他的动态分配是由操作系统进行释放,无需我们手工实现。
(5)分配效率不同。栈由操作系统自动分配,会在硬件层级对栈提供支持:分配专门的寄存器存放栈的地址,压栈出栈都有专门的指令执行,这就决定了栈的效率比较高。堆则是由C/C++提供的库函数或运算符来完成申请与管理,实现机制较为复杂,频繁的内存申请容易产生内存碎片。显然,堆的效率比栈要低得多。
(6)存放内容不同。栈存放的内容,函数返回地址、相关参数、局部变量和寄存器内容等。当主函数调用另外一个函数的时候,要对当前函数执行断点进行保存,需要使用栈来实现,首先入栈的是主函数下一条语句的地址,即扩展指针寄存器的内容(EIP),然后是当前栈帧的底部地址,即扩展基址指针寄存器内容(EBP),再然后是被调函数的实参等,一般情况下是按照从右向左的顺序入栈,之后是被调函数的局部变量,注意静态变量是存放在数据段或者BSS段,是不入栈的。出栈的顺序正好相反,最终栈顶指向主函数下一条语句的地址,主程序又从该地址开始执行。堆,一般情况堆顶使用一个字节的空间来存放堆的大小,而堆中具体存放内容是由程序员来填充的。
从以上可以看到,堆和栈相比,由于大量malloc()/free()或new/delete的使用,容易造成大量的内存碎片,并且可能引发用户态和核心态的切换,效率较低。栈相比于堆,在程序中应用较为广泛,最常见的是函数的调用过程由栈来实现,函数返回地址、EBP、实参和局部变量都采用栈的方式存放。虽然栈有众多的好处,但是由于和堆相比不是那么灵活,有时候分配大量的内存空间,主要还是用堆。
无论是堆还是栈,在内存使用时都要防止非法越界,越界导致的非法内存访问可能会摧毁程序的堆、栈数据,轻则导致程序运行处于不确定状态,获取不到预期结果,重则导致程序异常崩溃,这些都是我们编程时与内存打交道时应该注意的问题。
关键词: 堆和栈的区别
凡本网注明“XXX(非中国微山网)提供”的作品,均转载自其它媒体,转载目的在于传递更多信息,并不代表本网赞同其观点和其真实性负责。
大众网·海报新闻记者邢晨通讯员吕尚伟烟台报道养老服务人才匮乏、从业人员技能水平低,一直是困扰养老服务发展的难点、重点和堵点问题,为了
2022-10-28 18:36
大众网·海报新闻记者邢晨通讯员吕尚伟烟台报道为进一步改善老旧小区养老服务设施现状,加快推进养老服务体系建设,烟台市莱山区出台了《莱山
2022-10-28 18:46
大众网·海报新闻记者秦文济南报道记者从济南公交获悉,为方便蟠龙路、虎山路周边居民出行,填补蟠龙路、虎山路等部分路段公交空白,自10月29
2022-10-28 18:40
大众网·海报新闻记者秦文济南报道2021年9月29日,被誉为“万里黄河第一隧”的济南黄河济泺路隧道通车,这是山东省首条穿黄隧道。为主动融入“
2022-10-28 18:33
大众网·海报新闻记者汪雪然济南报道10月28日,由山东高速集团投资建设的济南至微山公路济宁新机场至枣菏高速段项目(以下简称“济微南段项目
2022-10-28 18:31
苹果手机数据迁移100g一般需要1-2个小时,主要看你的数据大不大,想要快一点的话,可以提前把旧iPhone升级到和新iPhone系统一样,然后充电充好
2022-10-28 15:39
京东买的黄金可以到实体店换吗是大家一定会讨论的,毕竟黄金作为时下最为保值的物件,很多人都会在其价格较低的时候购入。尤其是一些准备结婚
2022-10-28 15:51
香蕉酸奶是生活中比较常见的一种健康饮品,它含有多种营养成分,适量饮用对身体有一定的好处,喝香蕉酸奶一般是不会拉肚子的,不过可以促进肠
2022-10-28 15:47
铜鼠摆件摆在哪家里合适吗是很多人问的,毕竟我们日常生活里,其实最常见的就是一些气运摆件。不论是一个公司装修或者对于一个家庭来说,美好
2022-10-28 15:38
iphone传输数据卡在最后几分钟是比较正常的现象,大家不用太心急,可能是数据传输比较慢,显示十几分钟或者几分钟不动的话,可以多给一点时间
2022-10-28 15:51