c 記憶體分配管理

2021-06-27 06:08:14 字數 2075 閱讀 6847

1.1 先看看c++對記憶體分為哪幾個區?

1、棧區(stack)— 由編譯器自動分配釋放 ,存放函式的引數值,區域性變數的值等。其操作方式類似於資料結構中的棧。想知道為什麼效率高嗎?因為關於棧的操作如push整合在處理器的指令集中,效率很高,但是分配的記憶體容量有限。

2、堆區(heap) — 一般由程式設計師分配釋放, 若程式設計師不釋放,程式結束時可能由os** 。注意它與資料結構中的堆是兩回事,分配方式倒是類似於鍊錶。

3、全域性區(靜態區)(static)—,全域性變數和靜態變數的儲存是放在一塊的,初始化的全域性變數和靜態變數在一塊區域, 未初始化的全域性變數和未初始化的靜態變數在相鄰的另一塊區域。 

4、文字常量區—常量字串就是放在這裡的。

5、程式**區—存放函式體的二進位制**。

1.2 再給面試官談談new/delete和malloc/free的區別?

1、像我們的new/delete和malloc/free就是在上面所說的堆區上操作。程式設計師申請了記憶體,用完要記得釋放,否則就記憶體洩露了。而且多次申請釋放,會造成堆區碎片,這個需要注意下。

2、new/delete是操作符,而malloc/free是函式。前者可以被過載。前者可以有建構函式和析構函式。前者返回的某種型別物件的指標,後者返回void指標。

2.基於問題1,深入談談堆和棧

1、申請方式:

棧:函式內的區域性變數:int a = 10;

堆:new / malloc

2、申請後的系統響應:

棧:只要申請的空間大小《棧的剩餘空間,棧就分配。

堆:因為new,malloc都是c++封裝的,裡面做了這樣的事:首先明白windows有這麼乙個記錄空閒空間位址的鍊錶,c++遍歷該鍊錶,先找到第乙個空閒空間大小大於程式設計師申請的空間大小的位址(堆節點),將該堆節點從鍊錶中刪除,把該節點的空間分配給程式。對於大多數系統,會在這塊記憶體空間中的首位址處記錄本次分配的大小,這樣,**中的delete語句才能正確的釋放本記憶體空間。由於找到的堆結點的大小不一定正好等於申請的大小,系統會自動的將多餘的那部分重新放入空閒鍊錶中。

3、申請大小:

棧:預設是1m?還是2m?

堆:看系統的虛擬記憶體有多大了。(請記住堆是乙個節點為空閒記憶體空間的鍊錶。。)堆是向高位址擴充套件的資料結構,是不連續的記憶體區域。這是由於系統是用鍊錶來儲存的空閒記憶體位址的,自然是不連續的,而鍊錶的遍歷方向是由低位址向高位址。堆的大小受限於計算機系統中有效的虛擬記憶體。由此可見,堆獲得的空間比較靈活,也比較大。

4、申請效率:

棧:速度快,push,pop等指令都內建在處理器了,能不快嗎?

堆:相對慢(為什麼慢,可以看2,就知道它在申請的時候幹了多少事),還容易產生記憶體碎片。不過容量大,操作方便。

5、儲存內容:

棧(依次是):

主函式中後的下一條指令位址

然後是函式的各個引數(在大多數的c編譯器中,引數是由右往左入棧的)

函式中的區域性變數

堆:程式設計師隨意安排。

6、訪問效率:

先看看這段**:

int main()

這是在函式內,char陣列c,是在棧上。

char *p = "1234567890" ,其中雖然*p也是在棧上,但是"1234567890"在常量區。

再看看它們對應的彙編**:

10: a = c[1];

00401067 8a 4d f1 mov cl,byte ptr [ebp-0fh]

0040106a 88 4d fc mov byte ptr [ebp-4],cl

11: a = p[1];

0040106d 8b 55 ec mov edx,dword ptr [ebp-14h]

00401070 8a 42 01 mov al,byte ptr [edx+1]

00401073 88 45 fc mov byte ptr [ebp-4],al

可以看到在棧上的c只要兩行就能取到內容,而p要先去把常量區的內容放到edx中,再訪問。

說明純棧操作,效率是要高一些的。

7、總結

看看乙個經典**就什麼都懂了:

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

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

main() 

C 記憶體管理 記憶體分配

1 c 編譯的程式占用的記憶體分類 1 棧區 stack 程式執行時由編譯器自動分配,存放函式的引數值,區域性變數的值等。其操作方式類似於資料結構中的棧。程式結束時由編譯器自動釋放。2 堆區 heap 在記憶體開闢另一塊儲存區域。一般由程式設計師分配釋放,若程式設計師不釋放,程式結束時可能由os 注...

記憶體分配管理

系統中的記憶體分為棧 堆 全域性區 區 棧 由編譯器自動分配釋放,參訪函式的引數值,區域性變數,函式棧幀,函式呼叫過程。堆 由程式設計師自行分配想要的空間大小,c中的malloc等函式,c 中的new 全域性區 資料區 存放的是全域性變數和靜態變數,初始化的存在一起,未初始化的放一起,程式結束後由系...

記憶體分配 Go記憶體管理 記憶體分配一

go作為乙個比較新晚 新 的語言,自然借鑑前輩們的優點,比如說語言本身負責記憶體管理 對協程和高併發的高優支援 簡單高效的語法等。本篇及後續的幾篇要講的就是還沒提到的比較複雜的記憶體管理。學習記憶體管理 分配 前,如果有jvm的記憶體管理的基礎,會變得非常簡單,如果是第一次接觸記憶體管理,在看完go...