動態記憶體管理

堆疊配置與堆積配置(stack vs heap)

你的程式存進記憶體的每個值都住在某處,而對大多數變數你都有兩個地方可選:堆疊或堆積。它們都是行程記憶體中的區域,但行為差異之大,使得在兩者間抉擇成了 C 中最基本的決定之一。簡短版本:堆疊快又自動但綁定於函式呼叫;堆積有彈性但需手動。

堆疊配置是你宣告一個普通區域變數時自動發生的事,例如 int x 或 char buf[64]。空間在進入函式時保留、在它返回的瞬間釋放,只靠移動堆疊指標——沒有 malloc、沒有 free、沒有逐物件的記帳,而且極快。代價是兩個限制:生命期被函式呼叫所限(變數在返回時消失,所以你無法把它交還給呼叫者),而且大小必須是函式執行時已知的固定量,取自一塊相對較小的堆疊(常為數百萬位元組),所以巨大或大小未知的陣列不該放在那裡。堆積配置,透過 malloc 之類,去除了這兩個限制:區塊存活到你釋放為止(所以能比函式活得久、能回傳給呼叫者),而它的大小可以是任何在執行期算出的值,取自一塊大得多的池。代價是你得手動管理它——每次 malloc 都需要對應的 free,而這個領域的錯誤(洩漏、懸置指標、重複釋放)全都是堆積錯誤。

實務規則:當一個值的生命裝得進一個函式內、其大小不大且已知時,優先用堆疊——它更快且不會洩漏。當物件必須比建立它的函式活得久、必須被共享、必須成長、或太大或大小要到執行期才知道時,就改用堆積。一個有用的直覺:若你發現自己想回傳一個指向區域變數的指標,那就是你需要改用堆積的訊號。

void f(void) { char small[64]; /* 堆疊:自動,返回時釋放,固定大小 */ char *big = malloc(n); /* 堆積:存活到 free(big),大小於執行期得知 */ /* ... */ free(big); } /* small 在此自動消失 */

堆疊:自動又快,但綁定範圍且大小固定。堆積:有彈性且長壽,但需手動釋放。

這裡的堆疊是隨函式呼叫成長的記憶體區域——不是後進先出的堆疊資料結構。在它上面配置一個非常大的陣列可能讓堆疊溢位、使程式當機。

又称
automatic vs dynamic storagewhere to put a variable自動配置與動態配置