棧和堆的概念和區別

2021-09-25 12:14:13 字數 1947 閱讀 1258

在程序位址布局(如下圖),可見位址的分布情況,棧和堆所在的位置區域。

棧:由編譯器自動分配釋放,存放函式的引數值、區域性變數的值等。其操作方式類似於資料結構中的棧。每當乙個函式被呼叫,該函式返回位址和一些關於呼叫的資訊,比如某些暫存器的內容,被儲存到棧區。然後這個被呼叫的函式再為它的自動變數和臨時變數在棧區上分配空間,這就是c實現函式遞迴呼叫的方法。每執行一次遞迴函式呼叫,乙個新的棧框架就會被使用,這樣這個新例項棧裡的變數就不會和該函式的另乙個例項棧裡面的變數混淆。用於維護函式呼叫的上下文,離開了棧函式呼叫就沒法實現。棧通常在使用者空間的最高位址分配,通常有數兆位元組大小。

堆:是用來容納應用程式動態分布的記憶體區域,當程式使用malloc或new分配記憶體時,得到的記憶體來自堆裡,一般由程式設計師分配和釋放,若程式設計師不釋放,程式結束時有可能由os**。堆通常在棧的下方(低位址方向),在某些時候,堆一般比棧大很多,可以有幾十至數百兆位元組的容量。

\;linux程序位址空間布局

如下圖,這是乙個棧的例項這裡的棧底指標是0xbfffffff,而esp暫存器標明了棧頂,位址為0xbffffff4。在棧上壓入資料會導致esp減少,彈出資料使得esp增大。相反,直接減少esp的值也等效於在棧上開闢空間,直接增大esp的值等效於在棧上**空間。

棧儲存了乙個函式呼叫所需要的維護資訊,這被稱為堆疊幀。堆疊幀包含的內容如下:

1、函式的返回位址和引數。

2、 臨時變數:包括函式的非靜態區域性變數以及編譯器自動生成的其他臨時變數。

3、儲存的上下文:包括在函式呼叫前後需要保持不變的暫存器。

1、管理方式不同

棧由編譯器自動分配釋放。

堆空間的申請和釋放工作由程式設計師控制,手動釋放記憶體,容易產生記憶體洩漏的問題。

2、空間大小不同。

棧是向低位址擴充套件的資料結構,是一塊連續的記憶體區域,因此使用者能從棧獲得的空間較小,根據編譯器的不同有不同的取值,一般為2m(linux作業系統中為10m)。

堆是向高位址擴充套件的資料結構,是不連續的記憶體區域。因為系統是用鍊錶來儲存空閒記憶體位址的,且鍊錶的遍歷方向是由低位址,堆獲得的空間較靈活,也較大。

3、增長方向不同

棧區空間由高位址向低位址增長,而堆區位址由低位址向高位址增長。

4、是否產生碎片

對於堆來講,頻繁的malloc/free(new/delete)勢必會造成記憶體空間的不連續,從而造成大量的碎片,使程式效率降低,但對於棧來講,則不會存在這個問題。

5、分配方式不同

棧的分配和釋放是由編譯器完成的,堆都是程式中由malloc()函式動態申請分配並由free()函式釋放的。

6、分配效率不同

棧是機器系統提供的資料結構,計算機會在底層對棧提供支援,分配專門的暫存器存放棧的位址,壓棧出棧都有專門的指令執行,所以效率是比較高的。

堆是由malloc/new分配的記憶體,一般速度比較慢,而且容易產生記憶體碎片,堆的效率比棧要低得多。

7、系統響應方面

棧:只要棧的剩餘空間小於所申請空間,系統報異常提示棧溢位,否則將為程式提供記憶體。

堆:作業系統有乙個記錄空閒記憶體位址的鍊錶,當系統收到程式的申請時,會遍歷該鍊錶,尋找第乙個空間大於所申請空間的堆結點,然後將該結點從空閒結點鍊錶中刪除,並將該結點的空間分配給程式,另外,對於大多數系統,會在這塊記憶體空間中的首位址處記錄本次分配的大小,這樣**中的delete語句才能正確的釋放本記憶體空間。另外由於找到的堆結點的大小不一定正好等於申請的大小,系統會自動的將多餘的那部分重新放入空閒鍊錶中。

堆和棧的區別 概念

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

堆和棧的概念以及區別

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

堆和棧的概念詳解及區別

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