堆和棧區別

2021-08-08 23:02:51 字數 1279 閱讀 2956

①管理方式:棧由編譯器自動管理;堆由程式設計師控制,使用方便,但易產生記憶體洩露。

②生長方向:棧向低位址擴充套件(即」向下生長」),是連續的記憶體區域;堆向高位址擴充套件(即」向上生長」),是不連續的記憶體區域。這是由於系統用鍊錶來儲存空閒記憶體位址,自然不連續,而鍊錶從低位址向高位址遍歷。

③空間大小:棧頂位址和棧的最大容量由系統預先規定(通常預設2m或10m);堆的大小則受限於計算機系統中有效的虛擬記憶體,32位linux系統中堆記憶體可達2.9g空間。

④儲存內容:棧在函式呼叫時,首先壓入主調函式中下條指令(函式呼叫語句的下條可執行語句)的位址,然後是函式實參,然後是被調函式的區域性變數。本次呼叫結束後,區域性變數先出棧,然後是引數,最後棧頂指標指向最開始存的指令位址,程式由該點繼續執行下條可執行語句。堆通常在頭部用乙個位元組存放其大小,堆用於儲存生存期與函式呼叫無關的資料,具體內容由程式設計師安排。

⑤分配方式:棧可靜態分配或動態分配。靜態分配由編譯器完成,如區域性變數的分配。動態分配由alloca函式在棧上申請空間,用完後自動釋放。堆只能動態分配且手工釋放。

⑥分配效率:棧由計算機底層提供支援:分配專門的暫存器存放棧位址,壓棧出棧由專門的指令執行,因此效率較高。堆由函式庫提供,機制複雜,效率比棧低得多。windows系統中virtualalloc可直接在程序位址空間中分配一塊記憶體,快速且靈活。

⑦分配後系統響應:只要棧剩餘空間大於所申請空間,系統將為程式提供記憶體,否則報告異常提示棧溢位。

作業系統為堆維護乙個記錄空閒記憶體位址的鍊錶。當系統收到程式的記憶體分配申請時,會遍歷該鍊錶尋找第乙個空間大於所申請空間的堆結點,然後將該結點從空閒結點鍊錶中刪除,並將該結點空間分配給程式。若無足夠大小的空間(可能由於記憶體碎片太多),有可能呼叫系統功能去增加程式資料段的記憶體空間,以便有機會分到足夠大小的記憶體,然後進行返回。,大多數系統會在該記憶體空間首位址處記錄本次分配的記憶體大小,供後續的釋放函式(如free/delete)正確釋放本記憶體空間。

此外,由於找到的堆結點大小不一定正好等於申請的大小,系統會自動將多餘的部分重新放入空閒鍊錶中。

⑧碎片問題:棧不會存在碎片問題,因為棧是先進後出的佇列,記憶體塊彈出棧之前,在其上面的後進的棧內容已彈出。而頻繁申請釋放操作會造成堆記憶體空間的不連續,從而造成大量碎片,使程式效率降低。

可見,堆容易造成記憶體碎片;由於沒有專門的系統支援,效率很低;由於可能引發使用者態和核心態切換,記憶體申請的代價更為昂貴。所以棧在程式中應用最廣泛,函式呼叫也利用棧來完成,呼叫過程中的引數、返回位址、棧基指標和區域性變數等都採用棧的方式存放。所以,建議盡量使用棧,僅在分配大量或大塊記憶體空間時使用堆。

使用棧和堆時應避免越界發生,否則可能程式崩潰或破壞程式堆、棧結構,產生意想不到的後果。

堆和棧區別

一 預備知識 程式的記憶體分配 乙個由c c 編譯的程式占用的記憶體分為以下幾個部分 1 棧區 stack 由編譯器自動分配釋放 存放函式的引數值,區域性變數的值等。其 操作方式類似於資料結構中的棧。2 堆區 heap 一般由程式設計師分配釋放,若程式設計師不釋放,程式結束時可能由os回 收 注意它...

堆和棧區別

一 預備知識 程式的記憶體分配 乙個由c c 編譯的程式占用的記憶體分為以下幾個部分 1 棧區 stack 由編譯器自動分配釋放 存放函式的引數值,區域性變數的值等。其 操作方式類似於資料結構中的棧。2 堆區 heap 一般由程式設計師分配釋放,若程式設計師不釋放,程式結束時可能由os回 收 注意它...

堆和棧區別

堆區和棧區 程式執行時的記憶體區域 我們把記憶體分為堆空間和棧空間。棧空間比較小,但是讀取速度快 堆空間比較大,但是讀取速度慢 1.棧區 棧的特徵 資料只能從棧的頂端插入和刪除 把資料放入棧頂稱為入棧 push 從棧頂刪除資料稱為出棧 pop 簡單地說 先進後出2.堆 區分資料結構中堆 top k ...