堆疊與堆積的差異:比較記憶體區域的使用方式

執行中的程式主要使用兩個記憶體區域來存放資料。堆疊存放函式呼叫的框架,也就是區域變數、引數與返回位址。它由系統自動管理,速度非常快,但很小,且受限於函式呼叫的生命週期。堆積存放程式以 malloc 或 new 等方式明確要求的記憶體,會一直存活到被釋放為止。堆積靈活且大,但較慢,記憶體洩漏與碎片化也都發生在這裡。

項目堆疊堆積
用途函式呼叫的框架。區域變數、引數、返回位址生命週期比函式長,或大小事先不明的動態配置資料
配置方式自動。每次呼叫與返回時,堆疊指標會移動明確。malloc 與 free、new 與 delete,或垃圾回收器
速度非常快。只是移動指標較慢。配置器要尋找空閒區塊,並管理記錄
生命週期直到函式返回為止直到記憶體被釋放(或被垃圾回收)為止
大小有限(通常每個執行緒數 MB)上限只有可用的記憶體量
位置通常從高位址向下成長通常從低位址向上成長。兩者朝彼此成長
碎片化無可能發生。反覆配置與釋放會留下無法使用的空隙
執行緒每個執行緒都有專用的堆疊由所有執行緒共用,所以配置器必須是執行緒安全的
常見錯誤因深層遞迴或大型區域陣列造成的堆疊溢位記憶體洩漏、釋放後使用、重複釋放、記憶體不足

數值為具代表性的大致參考值,會因世代或產品而異。

適用於什麼情況

堆疊
小而短命、大小在編譯時已知的資料。一般的區域變數等。
堆積
大型資料、大小在執行時才會改變的資料,以及比建立它的函式存活更久的資料。

常見問題

為什麼堆疊的配置比堆積快?

因為堆疊的配置只是移動堆疊指標,而堆積的配置需要尋找空閒區塊,並更新配置器的記錄。

堆疊溢位的原因是什麼?

過度使用堆疊。深層遞迴、無限遞迴或非常大的區域陣列等,會超過堆疊大小的上限,使程式異常終止。

什麼是記憶體洩漏?

已配置卻沒有釋放的堆積記憶體,變得無法再利用。洩漏持續下去,程式的記憶體使用量會不斷增加。

執行緒會共用堆疊嗎?

不會。每個執行緒都有專用的堆疊,堆積則由所有執行緒共用。

相關名詞的解說

堆疊框
每次函式被呼叫時,在堆疊上配置的區域。放置返回位址、已儲存的暫存器、區域變數等,並在從函式返回時釋放。
堆疊指標
指向堆疊目前頂端位址的暫存器。在RISC-V中是sp(x2)。在多數ISA中,堆疊朝位址較小的方向延伸。
堆積區
程式執行中以 malloc 等配置所需大小的記憶體,並以 free 歸還的區域。反覆配置與釋放可能造成碎裂。

相關的比較