为什么栈的速度比堆要快

 

      在栈上分配的内存系统会自动地为其释放,例如在函数结束时,局部变量将不复存在,就是系统自动清除栈内存的结果。但堆中分配的内存则不然:一切由你负责,即使你退出了new表达式的所处的函数或者作用域,那块内存还处于被使用状态而不能再利用。好处就是如果你想在不同模块中共享内存,那么这一点正合你意,坏处是如果你不打算再利用这块内存又忘了把它释放掉,那么它就会霸占你宝贵的内存资源直到你的程序退出为止。 

       栈是机器系统提供的数据结构,计算机会在底层对栈提供支持:分配专门的寄存器存放栈的地址,压栈出栈都有专门的指令执行,这就决定了栈的效率比较高。堆则是C/C++函数库提供的,它的机制是很复杂的,例如为了分配一块内存,库函数会按照一定的算法(具体的算法可以参考数据结构/操作系统)在堆内存中搜索可用的足够大小的空间,如果没有足够大小的空间(可能是由于内存碎片太多),就有可能调用系统功能去增加程序数据段的内存空间,这样就有机会分到足够大小的内存,然后进行返回。显然,堆的效率比栈要低得多。 
  
       C/C++中,所有的方法调用都是通过栈来进行的,所有的局部变量,形式参数都是从栈中分配内存空间的。实际上也不是什么分配,只是从栈顶向上用就行,就好像工厂中的传送带(conveyorbelt)一样,StackPointer会自动指引你到放东西的位置,你所要做的只是把东西放下来就行.退出函数的时候,修改栈指针就可以把栈中的内容销毁.这样的模式速度最快,当然要用来运行程序了.需要注意的是,在分配的时候,比如为一个即将要调用的程序模块分配数据区时,应事先知道这个数据区的大小,也就说是虽然分配是在程序运行时进行的,但是分配的大小多少是确定的,不变的,而这个"大小多少"是在编译时确定的,不是在运行时. 看看LINUX内核源代码的存储管理部分,就知道操作系统是如何管理内存资源的。每个进程都有独立的地址空间,不过这只是虚地址,这也是我们通常所看到的地址,所以我们现在写程序时不会像早期的程序员担心内存不够用,对于LINUX用户进程最大可用3G的地址空间,另外的1G留给内核。这里讨论的堆或栈都是在虚拟地址空间上,各个进程都有自己独立堆、栈空间,否则,就象楼上一些哥们说的,一个进程飞了,那所有进程都得死。 
  
至于堆和栈哪个更快,从两方面来考虑:
      1.分配和释放,堆在分配和释放时都要调用函数(MALLOC,FREE),比如分配时会到堆空间去寻找足够大小的空间(因为多次分配释放后会造成空洞),这些都会花费一定的时间,具体可以看看MALLOC和FREE的源代码,他们做了很多额外的工作,而栈却不需要这些。
      2.访问时间,访问堆的一个具体单元,需要两次访问内存,第一次得取得指针,第二次才是真正得数据,而栈只需访问一次。另外,堆的内容被操作系统交换到外存的概率比栈大,栈一般是不会被交换出去的。 
  
      综上所述,站在操作系统以上的层面来看,栈的效率比堆高,对于应用程序员,这些都是透明的,操作系统做了很多我们看不到的东西。

 

10-07 12:31