堆(heap)與棧(stack)是程式儲存空間上的一組概念。
應用程式啟動時
程式啟動時,windows的pe裝載器會將pe檔案(可執行檔案,unix/linux 上是elf)的不同部分的內容裝入不同的記憶體區域。
程式的資料段包括.data段(全域性變數)和.rdata段(靜態變數和常量)。而pe裝載器只能從程式中讀出已初始化的全域性變數和靜態變數,並將它們放在的一段專門的初始化的資料的記憶體區域上。而未初始化的全域性變數和靜態變數則存放在一段專門的非初始化資料段
的記憶體區域上開闢空間,並且都被初始化為0。這二者合在一起被稱為data area。
程式的正文段(可再入程式,即可被多個程序共享的一串指令,是唯讀的)則是被裝載器裝入到被稱為code area記憶體區域。
程式中任何需要動態分配記憶體的變數(如使用malloc/free或new/delete)的記憶體分配是在堆進行。而區域性變數與自動變數的記憶體分配是在棧進行。
堆、棧
堆空間的記憶體分配屬於使用者級的記憶體分配,所分配的記憶體需要手動釋放,否則會造成記憶體洩漏。當然,在應用程式銷毀時,也能得到釋放。在32位的系統中堆得大小可達4g,可見堆得空間可以很大。但是堆的頻繁分配與釋放可能會帶來記憶體碎片,也可能會造成核心模式和使用者模式(unix/linux 的核心態和使用者態)頻繁切換和申請記憶體,帶來效能上的損失。例如可能會為了分配一塊記憶體,c/c++庫函式會按照一定的演算法
在堆記憶體中搜尋,看是否有可用的足夠大小的空間。如果沒有足夠大小的空間(可能是由於記憶體碎片太多),就有可能通過執行系統呼叫去增加程式資料段的記憶體空間,這樣就有機會分到足夠大小的記憶體,然後再返回。但是,我們要看到堆為我們提供了足夠的對記憶體使用的靈活性。特別是在某些時候,動態地分配記憶體能為我們大大的節約記憶體空間。
棧空間的記憶體分配則由系統負責管理的,是系統級的記憶體分配,一般不需要我們手動的控制。區域性變數、以及被呼叫的子程式的返回位址以及暫存器資訊都存放在棧中。我們知道棧是fifo(先進先出)的結構,因而棧空間上的記憶體始終是連續占用的,不會出現記憶體碎片。然而,棧的大小是有限制的。
例如,在vc6
下面,預設的棧空間大小是
1m。當然,可以修改:
開啟工程,依次操作選單如下:
project->setting->link
,在category
中選中output
,然後在
reserve
中設定堆疊的最大值和
commit
。堆與棧
堆與棧是兩個不同的概念,但是我們習慣上卻經常說「堆疊」這個詞,這造成了許多的誤會。因此,我們還要了解堆與棧的聯絡與區別。
我們用一張圖來直觀的說明堆、棧在記憶體上的位置關係。
堆空間 棧空間和堆疊平衡
堆 heap 與棧 stack 是程式儲存空間上的一組概念。應用程式啟動時 程式啟動時,windows的pe裝載器會將pe檔案 可執行檔案,unix linux 上是elf 的不同部分的內容裝入不同的記憶體區域。程式的資料段包括.data段 全域性變數 和.rdata段 靜態變數和常量 而pe裝載器...
堆空間 棧空間和堆疊平衡
堆和棧的區別 一 預備知識 程式的記憶體分配 乙個由c c 編譯的程式占用的記憶體分為以下幾個部分 1 棧區 stack 由編譯器自動分配釋放,存放函式的引數值,區域性變數的值等。其操作方式類似於資料結構中的棧。2 堆區 heap 一般由程式設計師分配釋放,若程式設計師不釋放,程式結束時可能由os ...
棧空間和堆空間
乙個由c c 編譯的程式占用的記憶體分為以下幾個部分 1 棧區 stack 又編譯器自動分配釋放,存放函式的引數值,區域性變數的值等,其操作方式類似於資料結構的棧。2 堆區 heap 一般是由程式設計師分配釋放,若程式設計師不釋放的話,程式結束時可能由os 值得注意的是他與資料結構的堆是兩回事,分配...