一般來說,程式就是與資料打交道,在執行某一程式功能的時侯,將該功能所需要的資料載入到記憶體中,然後在執行完畢的時候釋放掉該記憶體。
(1)、**區:程式的**(函式)放入**區,函式指標就指向**區,為唯讀區。
(2)、全域性區:用來存放全域性變數和static靜態變數,在main執行之前分配全域性區,可讀可寫。
(3)、bss段:存放未初始化的全域性變數。main函式執行之前清空bss段(全域性變數和static靜態變數未初始化列印輸出為0,而區域性變數未初始化列印為隨機值。
eg:
#include
int i;//未初始化的全域性變數,bss段
int j = 1;//初始化的全域性變數,全域性區
int main(void)
(4)、棧區:非static的區域性變數,包括函式的引數。記憶體是自動分配自動**的。
(5)、堆區:也叫自由區,malloc()、free()操作堆區,程式設計師完全掌控堆區記憶體的分配和**,容易產生記憶體的洩露。
(6)、常量區:常量和字串的字面值(」「)。
(7)、暫存器區:用來儲存棧頂指標和指令指標。
每個程序都先天設定了4g的虛擬記憶體位址(不是真實的位址,只是乙個編號)。虛擬記憶體開始時不對應任何記憶體,直接使用會引發段錯誤,不進入核心就接觸不到物理記憶體位址,只會接觸到虛擬記憶體位址。虛擬記憶體位址必須對映物理記憶體(或者硬碟上的檔案)以後才能儲存資料(資料儲存在物理記憶體上,列印位址為虛擬記憶體位址)。而記憶體分配其實就是虛擬記憶體位址對映物理記憶體的過程,記憶體**則是接觸對映關係的過程。
函式引數和區域性變數存放在棧中,當函式執行結束並且返回時,所有的區域性變數和引數就被系統自動清除掉了,為的是釋放掉他們所占用的記憶體空間。
全域性變數可以解決這個需要不斷重新為新的函式分配變數記憶體的問題,但是全域性變數永遠不會被釋放,而且由於全域性變數被所有類成員和函式共享,所以它們很容易被修改,不太安全。而使用堆可以解決這兩個問題。
堆是採用匿名的方式來儲存(儲存)資料的,只能通過指標才能訪問到這些匿名的資料,所以堆的安全性是最好的,而且堆的空間是可以程式設計師自行分配和釋放的,所以堆的自由度也是最高的。
由系統自動分配(如:int i;由系統自動為i在記憶體中開闢一塊4個位元組的記憶體空)
需要程式設計師自己申請,因此也需要指明變數大小(如:動態記憶體分配int * p = (int *)malloc(sizeof(int));由程式設計師自行申請)
只要系統剩餘空間大於所申請空間,系統將會為程式提供記憶體,否則將提示overflow,即棧溢位
系統收到程式申請空間的要求後,會遍歷整個作業系統用於記錄記憶體空閒位址的鍊錶,當找到乙個空間大於所申請空間的堆節點後,就會將該節點從記錄記憶體空閒位址的鍊錶中刪除。並將該節點的記憶體分配給程式,然後在這塊記憶體區域的首位址處記錄分配大小,這樣我們在使用delete來釋放記憶體的時候,delete才能夠正確地識別並刪除該記憶體區域的所有變數。另外,我們申請的空間與堆節點的記憶體空間不一定相等,這時系統就會自動將堆節點上多出的那一部分記憶體空間**到空閒鍊錶中。
在windows下,棧是一塊連續的記憶體區域,它的大小是2m,也有說是1m,總之該數值是乙個編譯時就確定的常數。是由系統預先根據棧頂的位址和棧的最大容量定義好的。加入申請的空間超過棧的空間,那麼就會提示overflow。因此別指望棧能儲存較大的資料。
堆是不連續的記憶體區域,各塊記憶體區域由鍊錶將其串聯起來,這些串聯起來的記憶體空間叫做堆,它的上限是由系統中的虛擬記憶體來定的,因此獲得的空間比較大,而且獲得空間的方式也比較靈活。
棧由系統自動分配,因此速度較快。但是程式設計師不能對其進行操作。
堆是由程式設計師分配的記憶體,一般速度比較慢,而且容易產生記憶體碎片,但用起來比較方便。
(棧底是高記憶體位址,棧頂是低記憶體位址)
在函式呼叫時,第乙個進棧的是被調函式下一行**的記憶體位址。其次是函式的引數(引數多於乙個時,最右邊的先進棧如get(a,b),b先進棧,a後進棧),最後是區域性變數。棧遵循先進後出原則,由於區域性變數最後進棧,那麼出棧(記憶體釋放)時,首先是釋放區域性變數所佔記憶體,其次是引數。當所有都已出棧,指標自然指到第乙個進棧的那行**的記憶體位址,程式根據該位址跳到被調函式的下一行繼續執行。
堆是一大堆不連續的空間,堆的機制比較複雜,容易產生碎片,效率也低的多,但是堆可以儲存相當大的資料,並且可以有程式設計師來安排,當我們需要建立乙個物件,可以被多個函式訪問但又不想其成為全域性的物件時,堆無疑是最好的選擇。由於堆疊各有優缺點,我們通常結合來使用,比如講大資料存放在堆中,而將指向該資料的指標存放在棧中。
堆,棧等概念以及記憶體洩露,記憶體溢位,記憶體越界等問題
在程序中記憶體被分為4個區域,分別是堆,棧,常量區,區。堆是我們程式設計師能夠直接控制的記憶體區域 既是new malloc 棧是程式自己控制的區域,常量區是存放全域性變數,字串常量的區域以及存放 的 區。在這之中堆疊是我們要注視的重點。下面我們通過乙個程式了解堆疊的生長方向以及資料的生長方向。in...
堆疊學習筆記
於李家凱老師的文章.由c c 編譯的程式占用的記憶體可以分為一下兩個部分 堆區 heap 一般由程式設計師分配釋放 比如malloc free,new delete 如果程式設計師不釋放,程式結束時可能會由作業系統進行 需要注意的是它和資料結構個中的堆是兩碼事,分配方式上堆類似於鍊錶。棧區 stac...
C 學習筆記6 記憶體的堆疊分配
所謂stack 棧 所謂heap 堆 stack,是存在於某作用域 scope 的乙個記憶體空間 memory space 例如當你呼叫函式,函式本身即會形成乙個stack用來放置它所接受的引數 以及返回位址。在函式本體 function body 內宣告的任何變數,其所使用的記憶體都取自上述sta...