新客立减

堆和栈的区别

堆与栈实际上是操作系统对进程占⽤的内存空间的两种管理⽅式,主要有如下⼏种区别:

1

)管理⽅式不同。栈由操作系统⾃动分配释放,⽆需我们⼿动控制;堆的申请和释放⼯作由程序员控制,容易产⽣内存泄漏;

2

)空间⼤⼩不同。每个进程拥有的栈的⼤⼩要远远⼩于堆的⼤⼩。理论上,程序员可申请的堆⼤⼩为虚拟内存的⼤⼩,进程栈的⼤⼩

64bits 

 Windows 

默认

 1MB

64bits 

 Linux 

默认

 10MB

3

)⽣长⽅向不同。堆的⽣长⽅向向上,内存地址由低到⾼;栈的⽣长⽅向向下,内存地址由⾼到低。

4

)分配⽅式不同。堆都是动态分配的,没有静态分配的堆。栈有

2

种分配⽅式:静态分配和动态分配。静态分配是由操作系统完成的,⽐

如局部变量的分配。动态分配由

alloca

函数进⾏分配,但是栈的动态分配和堆是不同的,他的动态分配是由操作系统进⾏释放,⽆需我们⼿

⼯实现。

5

)分配效率不同。栈由操作系统⾃动分配,会在硬件层级对栈提供⽀持:分配专门的寄存器存放栈的地址,压栈出栈都有专门的指令执

⾏,这就决定了栈的效率⽐较⾼。堆则是由

C/C++

提供的库函数或运算符来完成申请与管理,实现机制较为复杂,频繁的内存申请容易产⽣

内存碎⽚。显然,堆的效率⽐栈要低得多。

6

)存放内容不同。栈存放的内容,函数返回地址、相关参数、局部变量和寄存器内容等。当主函数调⽤另外⼀个函数的时候,要对当前

函数执⾏断点进⾏保存,需要使⽤栈来实现,⾸先⼊栈的是主函数下⼀条语句的地址,即扩展指针寄存器的内容(

EIP

),然后是当前栈帧

的底部地址,即扩展基址指针寄存器内容(

EBP

),再然后是被调函数的实参等,⼀般情况下是按照从右向左的顺序⼊栈,之后是被调函数

的局部变量,注意静态变量是存放在数据段或者

BSS

段,是不⼊栈的。出栈的顺序正好相反,最终栈顶指向主函数下⼀条语句的地址,主程

序⼜从该地址开始执⾏。堆,⼀般情况堆顶使⽤⼀个字节的空间来存放堆的⼤⼩,⽽堆中具体存放内容是由程序员来填充的。