堆和栈主要有以下几点不同:
1. 申请方式
栈:申请栈空间时不需要指明大小。例如,声明在函数中一个局部变量int b
; 系统自动在栈中为b开辟空间。
堆:申请堆空间时需要指明大小。例如,C中的malloc函数p1 = (char *)malloc(10)
。C++中的new运算符p2 = new char[10]
。但是p1、p2本身是在栈中的。
2. 分配方式
栈:栈是向低地址扩展的数据结构,是一块连续的内存的区域。只要栈的剩余空间大于所申请空间,系统将为程序提供内存,否则将报异常提示栈溢出。
堆:堆是向高地址扩展的数据结构,是不连续的内存区域。操作系统有一个记录空闲内存地址的链表,当系统收到malloc申请时,会遍历该链表,寻找第一个空间大于所申请空间的堆结点,然后将该结点从空闲结点链表中删除,并将该结点的空间分配给程序,另外,对于大多数系统,会在这块内存空间中的首地址处记录本次分配的大小,这样,代码中的delete语句才能正确的释放本内存空间。另外,由于找到的堆结点的大小不一定正好等于申请的大小,系统会自动的将多余的那部分重新放入空闲链表中。
3. 空间大小
栈:linux下默认的栈空间大小是8M或10M。
堆:堆的大小受限于计算机系统中有效的虚拟内存(虚拟内存中还有一部分空间要留给内核)。针对 Linux 操作系统而言,最高的1G 字节(从虚拟地址 0xC0000000 到 0xFFFFFFFF)由内核使用,称为内核空间。而较低的 3G 字节(从虚拟地址 0x00000000 到 0xBFFFFFFF)由各个进程使用,称为用户空间。
4. 存储内容
栈:存放局部变量、函数参数。存放在栈中的数据只在当前函数及下一层函数中有效,一旦函数返回了,这些数据也就自动释放了。
堆:堆中的具体内容可以通过程序员安排。