堆和栈的区别

2 篇文章 0 订阅

1.申请方式:栈由系统自动分配,速度快,但是程序员无法控制。 / 堆则是 由程序员自己申请,并指明大小,一般速度比较慢,容易产生碎片,不过用 起来比较方便,因为操控权在程序员的手中。由程序员进行释放。如果未进 行释放,就会产生野指针(指向已被释放的堆 空间),容易产生内存泄露。 (一般来说申请的空间是在堆区,而对应的指 针变量则储存在栈区)

2.大小:栈是由高地址指向低地址,大小固定,是一块连续的内存空间。如果 申请的空间的空间大于栈的剩余空间时,将提示overflow。
堆是由低地址指向高地址,是不连续的内存区域。这是由系统使用链 表来存储空闲内存地址的。而链表的遍历方向是由低地址向高地址,堆的大 小受限于计算机系统中有效的虚拟内存。当系统收到程序开辟空间的申请时
会遍历该链表,寻找第一个空间大于所申请空间的堆结点,然后将该节点 从空闲链表中删除,并将该节点的额空间分配给程序。另外,对于大多数系 统来说,会在这块空间的首地址处记录本次分配的大小,这样使得在free 的时候可以正确的释放内存空间,另外,找到的堆结点的大小不就一定正好 等于申请空间的大小,系统会自动的将多余的那部分重新放如空闲链表中。
(所以对于堆来讲,频繁的使用new/delete势必会导致空间的不连续,从 而导致大量的碎片,是程序效率降低,对于栈来讲就不存在这个问题 )

3.堆和栈的存储内容:栈:在函数调用时,第一个进栈的是主函数中下一条将 要执行的语句的地址(被调用的函数是当前所要执行的),然后是函数的各 个参数,参数是从右往左入栈的,然后是函数中的局部变量。(静态变量是 不存储在栈中,已初始化的静态变量存储在.data段,未初始化的静态变量 存储在.bss段)当本次函数调用结束后,局部变量先出栈,然后是参数,最 后是栈顶指针指向最开始的存的地址,程序依次推进。/堆:一般是在堆的 头部用一个字节存放堆的大小。然后在堆存入程序所指定的内容。

4.分配方式:堆是动态分配的,没有静态分配的堆。/栈有两种分配方式:静态分配和动态分配。静态分配是编译器完成的。比如局部变量的分配,函数调用时的入栈出栈等。动态分配由alloca函数进行分配,但是栈的动态分配和堆是不同的。他的动态分配是由编译器进行释放,无需程序员进行释放。(既然是在栈内申请内存,这就决定了其固有的局限性。其一是不适用于那些比创建它们的函数生命周期更长的结构;其二是不具可移植性,而且在没有传统堆栈的机器上很难高效地实现。这是因为当它的返回值直接传入另一个函数时会带来问题。这就决定了alloca()不宜使用在需要广泛移植的程序中,这也是很多人不太提倡使用alloca()的一个原因。)

栈是机器系统提供的数据结构,计算机会在底层对栈提供支持:分配专门的寄存器存放栈的地址,压栈出栈都有专门的指令执行,这就决定了栈的效率比较高。堆则是C/C++函数库提供的,它的机制是很复杂的,例如为了分配一块内存,库函数会按照一定的算法(具体的算法可以参考数据结构/操作系统)在堆内存中搜索可用的足够大小的空间,如果没有足够大小的空间(可能是由于内存碎片太多),就有可能调用系统功能去增加程序数据段的内存空间,这样就有机会分到足够大小的内存,然后进行返回。显然,堆的效率比栈要低得多。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值