棧和堆的區別

2021-09-02 07:22:01 字數 1927 閱讀 1559

記憶體主要分為五部分,從下到上(位址增加的方向)依次是**區、資料段(以初始化和未初始化)、堆、棧和共享區。其中堆和棧是相向而生,棧是向下增長,堆是向上增長。

**段:主要儲存一些可執行的**和字串常量。

資料段:儲存全域性資料和靜態資料

堆:程式執行開闢的動態記憶體區。

棧:儲存非static修飾區域性變數、函式引數和函式返回值。

共享區:動態庫就是位於此處,而且可以使用系統呼叫介面建立共享記憶體實現程序間通訊。

由於棧和堆區別常見於面試題,所以主要說一下棧和堆的區別:

1、管理方式不同;

2、空間大小不同;

3、能否產生碎片不同;

4、生長方向不同;

5、分配方式不同;

6、分配效率不同;

管理方式:對於棧來說,他的記憶體分配和釋放都是由編譯器自動處理,但是堆需要我們我們手動開闢空間,而且需要我們手動釋放(具體怎麼開闢和釋放:動態記憶體管理)

空間大小:首先他們都沒有固定的大小,在linux作業系統底下可以使用ulimit -a修改他們大小。一般堆大約棧1g左右吧,但是棧是幾m。

產生碎片:堆的話,頻繁的使用new和delete,勢必會造成記憶體的不連續,也就是記憶體碎片,其實這個就是動態順序表的乙個缺點,會造成記憶體碎片。但是棧不會造成記憶體碎片,因為棧是後進先出,pop的時候永遠都不可能中間記憶體先出去,所以不會造成記憶體碎片。

分配方式:堆只有動態分配,但是棧有靜態分配和動態分配兩種方式。棧的靜態分配是由編譯器自動分配,而動態分配可以呼叫alloca函式,但是釋放還是由編譯器自己釋放。

分配效率:棧是機器系統提供的資料結構,計算機會在底層對棧提供支援:分配專門的暫存器存放棧的位址,壓棧出棧都有專門的指令執行,這就決定了棧的 效率比較高。堆則是c/c++函式庫提供的,它的機制是很複雜的,例如為了分配一塊記憶體,庫函式會按照一定的演算法(具體的演算法可以參考資料結構/操作系 統)在堆記憶體中搜尋可用的足夠大小的空間,如果沒有足夠大小的空間(可能是由於記憶體碎片太多),就有可能呼叫系統功能去增加程式資料段的記憶體空間,這樣就 有機會分到足夠大小的記憶體,然後進行返回。顯然,堆的效率比棧要低得多。

從這裡我們可以看到,堆和棧相比,由於大量 new/delete的使用,容易造成大量的記憶體碎片;由於沒有專門的系統支援,效率很低;由於可能引發 使用者態和核心態的切換,記憶體的申請,代價變得更加昂貴。所以棧在程式中是應用最廣泛的,就算是函式的呼叫也利用棧去完成,函式呼叫過程中的引數,返回地 址,ebp和區域性變數都採用棧的方式存放。所以,我們推薦大家盡量用棧,而不是用堆。

雖然棧有如此眾多的好處,但是由於和堆相比不是那麼靈活,有時候分配大量的記憶體空間,還是用堆好一些。

無論是堆還是棧,都要防止越界現象的發生(除非你是故意使其越界),因為越界的結果要麼是程式崩潰,要麼是摧毀程式的堆、棧結構,產生以想不到的結 果,就算是在你的程式執行過程中,沒有發生上面的問題,你還是要小心,說不定什麼時候就崩掉,那時候debug可是相當困難的:)

malloc工作機制:

malloc函式的實質體現在,它有乙個將可用的記憶體塊連線為乙個長長的列表的所謂空閒鍊錶(堆記憶體)。呼叫malloc函式時,它沿連線表尋找乙個大到足以滿足使用者請求所需要的記憶體塊。然後,將該記憶體塊一分為二(一塊的大小與使用者請求的大小相等,另一塊的大小就是剩下的位元組)。接下來,將分配給使用者的那塊記憶體傳給使用者,並將剩下的那塊(如果有的話)返回到連線表上。呼叫free函式時,它將使用者釋放的記憶體塊連線到空閒鏈上。到最後,空閒鏈會被切成很多的小記憶體片段,如果這時使用者申請乙個大的記憶體片段,那麼空閒鏈上可能沒有可以滿足使用者要求的片段了。於是,malloc函式請求延時,並開始在空閒鏈上翻箱倒櫃地檢查各記憶體片段,對它們進行整理,將相鄰的小空閒塊合併成較大的記憶體塊。如果無法獲得符合要求的記憶體塊,malloc函式會返回null指標,因此在呼叫malloc動態申請記憶體塊時,一定要進行返回值的判斷。

堆和棧區別

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

堆和棧區別

管理方式 棧由編譯器自動管理 堆由程式設計師控制,使用方便,但易產生記憶體洩露。生長方向 棧向低位址擴充套件 即 向下生長 是連續的記憶體區域 堆向高位址擴充套件 即 向上生長 是不連續的記憶體區域。這是由於系統用鍊錶來儲存空閒記憶體位址,自然不連續,而鍊錶從低位址向高位址遍歷。空間大小 棧頂位址和...

堆和棧區別

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