可分为几个方面去区分:
1. 从管理方式上:
从定义上:堆是由new和malloc开辟的一块内存,由程序员手动管理,栈是编译器自动管理的内存,存放函数的参数和局部变量。
2.空间大小不同:
在Window下,栈的大小是2MB,Linux下,默认栈空间大小为8MB;在Window下,堆的大小一般小于2GB。
PS:通常系统默认的堆栈的内存大小可以改变;1、通过程序代码控制 2、通过配置程序进行设置,注意单位也是字节,byte
3.能否产生碎片不同;
对于堆来讲,频繁的new/delete势必会造成内存空间的不连续, 从而造成大量的碎片,使程序效率降低。
对于栈来讲,则不会存在这个问题,因 为栈是先进后出的队列,他们是如此的一一对应,以至于永远都不可能有一个内存块从栈中间弹出,在他弹出之前,在他上面的后进的栈内容已经被弹出。
4.生长方向不同:
对于堆来讲,生长方向是向上的,也就是向着内存地址增加的方向;
对于栈来讲,它的生长方向是向下的,是向着内存地址减小的方向增长。
5.分配方式不同:
堆都是动态分配的;栈有静态和动态两种分配方式。静态分配由编译器完成,比如局部变量的分配。动态分配由alloca函数进行、但栈的动态分配和堆是不同的,它的动态分配由编译器进行释放,无需我们手工实现。
6、分配效率不同;
栈是机器系统提供的数据结构,计算机会在底层对栈提供支持:分配专门的寄存器存放栈的地址,压栈出栈都有专门的指令执行,这就决定了栈的效率比较高。堆则是c/c++库函数提供的,机制很复杂。库函数会按照一定的算法进行分配。显然,堆的效率比栈要低得多。
低 ->|-----------------|
| 全局量(所有已初始化量 .data, |
| 未初始化量 .bss ) |
堆起始->|-----------------|
| 堆向高地址增长 |
| |
| |
| 自由空间 |
| |
| |
| 栈向低地址增长 |
高 栈起始->|-----------------|
在内存中,“堆”和“栈”共用全部的自由空间,只不过各自的起始地址和增长方向不同,它们之间并没有一个固定的界限,如果在运行时,“堆”和 “栈”增长到发生了相互覆盖时,称为“栈堆冲突”,系统肯定垮台。由于开销方面的原因,各种编译在实现中都没有考虑解决这个问题,只有靠设计者自己解决,比如增加内存等。
虽然栈有如此众多的好处,但是由于和堆相比不是那么灵活,有时候分配大量的内存空间,还是用堆好一些。
无论是堆还是栈,都要防止越界现象的发生(除非你是故意使其越界),因为越界的结果要么是程序崩溃,要么是摧毁程序的堆、栈结构,产生以想不到的结果,就算是在你的程序运行过程中,没有发生上面的问题,你还是要小心,说不定什么时候就崩掉,那时候debug可是相当困难的。