浅谈堆和栈

文章包括以下内容:

  • 堆和栈是什么
  • 堆和栈的区别
  • 程序怎样使用堆和栈

堆和栈是什么

看了很多文章,讲的内容都很多,但关于堆和栈的定义到底是什么?很多是没提及的。

堆和栈是两种不同内存分配方式所获得的内存区域的统称。栈是用来存储函数内部临时使用的变量(局部变量),以及函数调用时所用参数的内存区域;堆是用来存储程序运行时的任意数据及对象的内存区域。

堆和栈的区别

分配和释放方式

堆和栈都是在程序运行时所申请分配的。但对于栈中数据的存储和释放是由编译器自动完成的,不需要程序猿参与;而堆的内存空间,是需要在编写的程序中申请分配或释放的(这里针对的是C、C++这样的编程语言;对于Java、Go等编程语言来说,编译器对堆也是有申请分配和回收机制的)。

无论是C还是C++,如果没有在程序中明确的释放堆的内存空间,那么即使在程序中的任务处理完毕后,该内存空间仍会一直残留,这种现象称为内存泄露

分配的效率

栈结构是系统提供的数据结构,操作系统会在底层对栈提供支持,例如,分配专门的寄存器存放栈的地址,压栈出栈都有专门的执行指令(参照汇编语言中的push、pop),而且栈的内存区域是连续的,这就决定了栈的效率比较高。

堆则不同,比如程序想申请一块堆内存,操作系统会遍历记录空闲内存地址的链表,寻找第一个空间大于所申请空间的堆节点,然后将该节点从空闲节点链表中删除,并将该节点的空间分配给该程序。很显然,堆的分配效率比栈要慢的多。

碎片问题

对堆来说,频繁分配和释放(C语言中的 malloc / free)不同大小的堆空间势必会造成内存空间的不连续,从而造成大量碎片,导致程序运行效率降低;而对栈来讲,则不存在这个问题。

内存空间大小问题

由于操作系统是用链表来存储空闲内存地址(内存区域不连续)的,同时链表的遍历方向是由低地址向高地址进行的。因此,堆内存的申请大小受限于计算机系统中有效的虚拟内存。

而栈则不同,它是一块连续的内存区域,其地址的增长方向是向下进行的,向内存地址减小的方向增长。由此可见,栈顶地址、栈的最大容量一般都是由操作系统预先规定好的,如果申请的内存空间超过栈的剩余空间时,将会提示栈溢出错误。相对于堆来说,程序可以从栈中获得的内存空间相对较小。

程序怎样使用堆和栈

这块内容感觉自己理解的不太透彻,就不造作了。

  • 可以认真读读《程序是怎样跑起来的》中第九章、第十章
  • 还有这篇函数调用栈

这里说一下,因为高级语言的代码我们看不出程序对栈的具体操作;机器语言都是数值序列,我们又看不懂(也许有人可以看懂,😄)。所以只能靠汇编语言了。

参考

  • 《程序是怎样跑起来的》
  • https://zhuanlan.zhihu.com/p/101531768
  • https://article.itxueyuan.com/yeq4Q
  • https://zhuanlan.zhihu.com/p/103454656
  • http://c.biancheng.net/c/stack/
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值