2019.10.28C++學習筆記——堆、棧和存儲空間分類

C++學習筆記——堆、棧和存儲空間分類

堆和棧:

(1)管理方式:堆中資源由程序員控制(通過malloc/free、new/delete,容易產生memory leak),棧資源由編譯器自動管理。

(2)系統響應:對於堆,系統有一個記錄空閒內存地址的鏈表,當系統收到程序申請時,遍歷該鏈表,尋找第一個大於所申請空間的空間的堆結點,刪除空閒結點鏈表中的該結點,並將該結點空間分配給程序(大多數系統會在這塊內存空間首地址記錄本次分配的大小,這樣delete才能正確釋放本內存空間,另外,系統會將多餘的部分重新放入空閒鏈表中)。對於棧,只要棧的剩餘空間大於所申請空間,系統就會爲程序分配內存,否則報異常出現棧空間溢出錯誤。

(3)空間大小:堆是不連續的內存區域(因爲系統是用鏈表來存儲空閒內存地址的,自然不是連續),堆的大小受限於計算機系統中有效的虛擬內存(32位機器上理論上是4G大小),所以堆的空間比較靈活,比較大。棧是一塊連續的內存區域,大小是操作系統預定好的,windows下棧大小是2M(也有是1M,在編譯時確定,VC中可設置)。

(4)碎片問題:對於堆,頻繁的new/delete會造成大量內存碎片,降低程序效率。對於棧,它是一個先進後出(first-in-last-out)的結構,進出一一對應,不會產生碎片。

(5)生長方向:堆向上,向高地址方向增長;棧向下,向低地址方向增長。

(6)分配方式:堆是動態分配(沒有靜態分配的堆)。棧有靜態分配和動態分配,靜態分配由編譯器完成(如函數局部變量),動態分配由alloca函數分配,但棧的動態分配資源由編譯器自動釋放,無需程序員實現。

(7)分配效率:堆由C/C++函數庫提供,機制很複雜,因此堆的效率比棧低很多。棧是機器系統提供的數據結構,計算機在底層對棧提供支持,分配專門的寄存器存放棧地址,提供棧操作專門的指令。

C++內存結構:

在C++中,內存分成5個區,他們分別是堆、棧、自由存儲區、全局/靜態存儲區和常量存儲區。

:就是那些由編譯器在需要的時候分配,在不需要的時候自動清楚的變量的存儲區。裏面的變量通常是局部變量、函數參數等。

:就是那些由new分配的內存塊,他們的釋放編譯器不去管,由我們的應用程序去控制,一般一個new就要對應一個delete。如果程序員沒有釋放掉,那麼在程序結束後,操作系統會自動回收。

自由存儲區:就是那些由malloc等分配的內存塊,他和堆是十分相似的,不過它是用free來結束自己的生命的。(堆和自由存儲區其實可以看作是同一塊區域,new底層實現代碼中調用了malloc,new可以看成是malloc智能化的高級版本)

全局/靜態存儲區:全局變量和靜態變量被分配到同一塊內存中,在以前的C語言中,全局變量又分爲初始化的和未初始化的(初始化的全局變量和靜態變量在一塊區域,未初始化的全局變量與靜態變量在相鄰的另一塊區域,同時未被初始化的對象存儲區可以通過void*來訪問和操縱,程序結束後由系統自行釋放),在C++裏面沒有這個區分了,他們共同佔用同一塊內存區。

常量存儲區:這是一塊比較特殊的存儲區,他們裏面存放的是常量,不允許修改。(當然,通過非正當手段也可以修改,而且方法很多)

內存區域的劃分在代碼中的例子:

int   b;    
//main.cpp
int   a   =   0;   //全局初始化區
char   *p1;        //全局未初始化區
main(){int   b;                     //棧
char   s[]   =   "abc";      // 棧
char   *p2;                  //棧
char   *p3   =   "123456";   // 123456/0在常量區,p3在棧上。
static int c = 0// 全局(靜態)初始化區
p1 =   (char *)malloc(10)
p2 =   (char *)malloc(20)    // 分配得來得10和20字節的區域就在堆區。
strcpy(p1, "123456");        // 123456/0放在常量區,編譯器可能會將它與p3所指向的"123456"優化成一個地方。
}

P.S. 在開闢內存時,使用new[]開闢了數組空間後,釋放空間一定用delete[]才能在釋放空間時告訴編譯器釋放的是數組空間。

P.S.

p1 = (char *)malloc(10);

在上面這行代碼中,爲指針p1開闢了10個字節的空間,這10個字節的空間在堆中,即自由存儲區,但是指針p1存儲在棧中。具體含義爲在棧中存儲了一個指針,這個指針指向堆中的一塊內存。

參考:
C++中堆和棧的區別

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章