記憶體分配中的堆 棧 靜態區 唯讀區

2021-09-24 04:59:49 字數 2886 閱讀 7510

**:

記憶體中的棧區處於相對較高的位址以位址的增長方向為上的話,棧位址是向下增長的,棧中分配區域性變數空間,堆區是向上增長的用於分配程式設計師申請的記憶體空間。另外還有靜態區是分配靜態變數,全域性變數空間的;唯讀區是分配常量和程式**空間的;以及其他一些分割槽。對於常量,在實際情況中,是會復用的,比如變數a和b都賦值為」abc」則實際上他們指向同一塊位址。

main.cpp 

int a = 0; //全域性初始化區

char *p1; //全域性未初始化區

main()

堆和棧的第乙個區別就是申請方式不同:棧(英文名稱是stack)是系統自動分配空間的,例如我們定義乙個 char a;系統會自動在棧上為其開闢空間。而堆(英文名稱是heap)則是程式設計師根據需要自己申請的空間,例如malloc(10);開闢十個位元組的空間。由於棧上的空間是自動分配自動**的,所以棧上的資料的生存週期只是在函式的執行過程中,執行後就釋放掉,不可以再訪問。而堆上的資料只要程式設計師不釋放空間,就一直可以訪問到,不過缺點是一旦忘記釋放,在程式執行過程中會造成記憶體洩露,只能等待程式結束時由系統**。

1.申請後系統的響應

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

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

也就是說堆會在申請後還要做一些後續的工作這就會引出申請效率的問題

p1 = (char *)malloc(10);   //在c中malloc函式

p2 = (char *)new(10); //在c++中用new運算子

//******注意p1、p2本身是在棧中的。

2.申請效率的比較

棧由系統自動分配,速度較快。但程式設計師是無法控制的。 

堆是由new分配的記憶體,一般速度比較慢,而且容易產生記憶體碎片,不過用起來最方便. 

3.申請大小的限制 

棧:在windows下,棧是向低位址擴充套件的資料結構,是一塊連續的記憶體的區域。這句話的意思是棧頂的位址和棧的最大容量是系統預先規定好的,在 windows下,棧的大小是2m(也有的說是1m,總之是乙個編譯時就確定的常數),如果申請的空間超過棧的剩餘空間時,將提示overflow。因此,能從棧獲得的空間較小。 

堆:堆是向高位址擴充套件的資料結構,是不連續的記憶體區域。這是由於系統是用鍊錶來儲存的空閒記憶體位址的,自然是不連續的,而鍊錶的遍歷方向是由低位址向高位址。堆的大小受限於計算機系統中有效的虛擬記憶體。一般來講在32位系統下,堆記憶體可以達到4g的空間。由此可見,堆獲得的空間比較靈活,也比較大。 

4.堆和棧中的儲存內容 

棧: 在函式呼叫時,第乙個進棧的是主函式中函式呼叫後的下一條指令(函式呼叫語句的下一條可執行語句)的位址,然後是函式的各個引數,在大多數的c編譯器中,引數是由右往左入棧的,然後是函式中的區域性變數。注意靜態變數是不入棧的。

堆:一般是在堆的頭部用乙個位元組存放堆的大小。堆中的具體內容有程式設計師安排。 

5.訪問效率的比較

使用棧就象我們去飯館裡吃飯,只管點菜(發出申請)、付錢、和吃(使用),吃飽了就走,不必理會切菜、洗菜等準備工作和洗碗、刷鍋等掃尾工作,他的好處是快捷,但是自由度小。 

使用堆就象是自己動手做喜歡吃的菜餚,比較慢,但是比較符合自己的口味,而且自由度大

6. 碎片問題:棧不會產生碎片,堆會產生碎片

8.全域性變數、區域性變數、靜態全域性變數、靜態區域性變數的區別是:

生存週期不同作用範圍不同分配方式不同

全域性變數具有全域性作用域。全域性變數只需在乙個原始檔中定義,就可以作用於所有的原始檔。當然,其他不包含全域性變數定義的原始檔需要用extern 關鍵字再次宣告這個全域性變數。

區域性變數也只有區域性作用域,它是自動物件(auto),它在程式執行期間不是一直存在,而是只在函式執行期間存在,函式的一次呼叫執行結束後,變數被撤銷,其所占用的記憶體也被收回。

靜態區域性變數具有區域性作用域,它只被初始化一次,自從第一次被初始化直到程式執行結束都一直存在,它和全域性變數的區別在於全域性變數對所有的函式都是可見的,而靜態區域性變數只對定義自己的函式體始終可見。

靜態全域性變數也具有全域性作用域,它與全域性變數的區別在於如果程式包含多個檔案的話,它作用於定義它的檔案裡,不能作用到其它檔案裡,即被static關鍵字修飾過的變數具有檔案作用域。這樣即使兩個不同的原始檔都定義了相同名字的靜態全域性變數,它們也是不同的變數。

從分配記憶體空間看:全域性變數,靜態區域性變數,靜態全域性變數都在靜態儲存區分配空間,而區域性變數在棧裡分配空間。

從以上分析可以看出,把區域性變數改變為靜態變數後是改變了它的儲存方式即改變了它的生存期。把全域性變數改變為靜態變數後是改變了它的作用域,限制了它的使用範圍。因此static 這個說明符在不同的地方所起的作用是不同的。

記憶體分配模式 靜態區 堆 棧

靜態區 儲存自動全域性變數和static變數 包括static全域性和區域性變數 靜態區的內容在總個程式的生命週期內都存在,由編譯器在編譯的時候分配。堆 由malloc系列函式或new操作符分配的記憶體,其生命週期由free或delete決定。在沒有釋放之前一直存在,直到程式結束,其特點是使用靈活,...

記憶體的使用 棧區 堆區 靜態區 唯讀區

記憶體的使用感覺好亂啊,需要整理一下!於是參考c primer與網上資源,整理如下 一 綜述 記憶體中的棧區分配的是區域性變數和函式的引數值的空間,棧的生長方向是從高往低的 堆區是向上增長的用於分配程式設計師申請的記憶體空間 比如new 申請的動態記憶體 注意它與資料結構中的堆是兩回事,分配方式倒是...

C 記憶體 堆疊靜態儲存區

學習c 如果不了解記憶體分配是一件非常可悲的事情。而且,可以這樣講,乙個c 程式設計師無法掌握記憶體 無法了解記憶體,是不能夠成為乙個合格的c 程式設計師的。一 記憶體基本構成 可程式設計內存在基本上分為這樣的幾大部分 靜態儲存區 堆區和棧區。他們的功能不同,對他們使用方式也就不同。靜態儲存區 內存...