堆和栈的区别
堆与栈实际上是操作系统对进程占⽤的内存空间的两种管理⽅式,主要有如下⼏种区别:
(
1
)管理⽅式不同。栈由操作系统⾃动分配释放,⽆需我们⼿动控制;堆的申请和释放⼯作由程序员控制,容易产⽣内存泄漏;
(
2
)空间⼤⼩不同。每个进程拥有的栈的⼤⼩要远远⼩于堆的⼤⼩。理论上,程序员可申请的堆⼤⼩为虚拟内存的⼤⼩,进程栈的⼤⼩
64bits
的
Windows
默认
1MB
,
64bits
的
Linux
默认
10MB
;
(
3
)⽣长⽅向不同。堆的⽣长⽅向向上,内存地址由低到⾼;栈的⽣长⽅向向下,内存地址由⾼到低。
(
4
)分配⽅式不同。堆都是动态分配的,没有静态分配的堆。栈有
2
种分配⽅式:静态分配和动态分配。静态分配是由操作系统完成的,⽐
如局部变量的分配。动态分配由
alloca
函数进⾏分配,但是栈的动态分配和堆是不同的,他的动态分配是由操作系统进⾏释放,⽆需我们⼿
⼯实现。
(
5
)分配效率不同。栈由操作系统⾃动分配,会在硬件层级对栈提供⽀持:分配专门的寄存器存放栈的地址,压栈出栈都有专门的指令执
⾏,这就决定了栈的效率⽐较⾼。堆则是由
C/C++
提供的库函数或运算符来完成申请与管理,实现机制较为复杂,频繁的内存申请容易产⽣
内存碎⽚。显然,堆的效率⽐栈要低得多。
(
6
)存放内容不同。栈存放的内容,函数返回地址、相关参数、局部变量和寄存器内容等。当主函数调⽤另外⼀个函数的时候,要对当前
函数执⾏断点进⾏保存,需要使⽤栈来实现,⾸先⼊栈的是主函数下⼀条语句的地址,即扩展指针寄存器的内容(
EIP
),然后是当前栈帧
的底部地址,即扩展基址指针寄存器内容(
EBP
),再然后是被调函数的实参等,⼀般情况下是按照从右向左的顺序⼊栈,之后是被调函数
的局部变量,注意静态变量是存放在数据段或者
BSS
段,是不⼊栈的。出栈的顺序正好相反,最终栈顶指向主函数下⼀条语句的地址,主程
序⼜从该地址开始执⾏。堆,⼀般情况堆顶使⽤⼀个字节的空间来存放堆的⼤⼩,⽽堆中具体存放内容是由程序员来填充的。