这个问题,经常会被面试官问到,所以我总结了一下堆和栈的区别,我是从8个方面进行对其分析:
1.管理方式:栈是由编译器进行管理的,而堆是由程序员自己对其管理的,使用比较方便,但是容易产生内存泄漏。
2.生长方向:栈是由高地址向低地址方向生长,是一段连续的内存区域,而堆是由低地址向高地址方向生长,是一段不连续的内存区域,是由链表进行对其遍历的。
3.空间大小:栈顶地址和栈的最大容量由系统预先规定(通常默认2M或10M,Linux中可以通过ulimit -s 命令对其修改,修改之后会增加内存开销和启动时间);堆的大小则受限于计算机系统中有效的虚拟内存,32位Linux系统中堆内存可达2.9G左右的空间。
4.分配方式:栈是由编译器进行分配的,主要有两种分配方式:静态分配和动态分配,静态分配是有编译器完成的,如:局部变量,而动态分配是malloc在申请空间,用完之后自动释放。而堆只能动态开辟由程序员进行释放。
5.分配效率:栈由计算机底层提供支持,分配专门的寄存器存放栈地址,压栈出栈由专门的指令执行,因此效率较高。堆由函数库提供,机制复杂,效率比栈低得多。
6.内存碎片问题:栈不会产生内存碎片的,因为栈是先进后出的队列,内存块弹出栈之前,在其上面的后进的栈内容已弹出。而频繁的申请和释放堆空间,则会导致堆空间的不连续,因此会产生大量的内存碎片,导致程序的效率低。
7.存储内容:栈在函数调用时,首先压入调用函数中下条指令(函数调用语句的下条可执行语句)的地址,然后是函数实参,然后是被调函数的局部变量。本次调用结束后,局部变量先出栈,然后是参数,最后栈顶指针指向最开始存的指令地址,程序由该点继续运行下条可执行语句。堆通常在头部用一个字节存放其大小,堆用于存储生存期与函数调用无关的数据,具体内容由程序员安排。
8.分配后系统的响应:对栈而言:只要栈的剩余空间大于所申请空间,系统则会为它正常提供内存,否则,则会报告异常提示栈溢出。对堆而言:操作系统为堆维护一个纪录空闲内存的链表,当程序员需要申请空间时,操作系统就会对其进行遍历,找到第一个大于用户所申请的堆节点,然后将该节点从空闲内存链表中删除,并将该节点内存空间分配给程序,若没有足够大小的空间(可能由于内存碎片太多),然后操作系统就有可能调用系统功能去增加程序数据段的内存空间,以便有机会分到足够大小的内存,然后进行返回,大多数系统会在该内存空间首地址处记录本次分配的内存大小,供后续的释放函数(如free/delete)正确释放本内存空间。
以上就是我所总结的堆和栈的区别,如有错误请指正!!!各位同仁如果还能总结出其他区别。请评论区留言。