1. 程式人生 > >內存分配方式

內存分配方式

計算機 malloc bsp 虛擬內存 剩余空間 成員 容易 class 存儲

操作系統復習 內存的深入理解

內存構成

程序代碼區—存放函數體的二進制代碼。

全局區(靜態區)(static):全局變量和靜態變量的存儲是放在一塊的,初始化的全局變量和靜態變量在一塊區域,未初始化的全局變量和未初始化的靜態變量在相鄰的另一塊區域。程序結束後由系統釋放。

棧區(stack):由編譯器自動分配釋放,存放函數的參數值,局部變量的值等。其操作方式類似於數據結構中的棧。

堆區(heap): 一般由程序員分配釋放,若程序員不釋放,程序結束時可能由OS回收。註意它與數據結構中的堆是兩回事,分配方式類似鏈表。

內存分配方式

從靜態存儲區域分配 內存在程序編譯的時候就已經分配好,這塊內存在程序的整個運行期間都存在。例如全局變量,static變量。 初始化的全局變量和靜態變量在一塊區域,未初始化的全局變量和未初始化的靜態變量在相鄰的另一塊區域。

在棧上創建 在執行函數時,函數的參數值,內局部變量的存儲單元都可以在棧上創建。函數執行結束時這些存儲單元自動被釋放。棧內存分配運算內置於處理器的指令集中,效率很高,但是分配的內存容量有限。

從堆上分配,亦稱動態內存分配 程序在運行的時候用malloc或new申請任意多少的內存,程序員自己負責在何時用free或delete釋放內存。動態內存的生存期由程序員決定,使用非常靈活,但問題也最多。

int a = 0; //靜態存儲區(初始化區域) 

char *p1; //靜態存儲區(未初始化區域)

void example() 

{

int b;	         //棧

char s[] = "abc";	//棧 

char *p2;	         //棧 

static int c =0;	//靜態存儲區(初始化區域) 

p1 = (char *)malloc(10); 

p2 = (char *)malloc(20);//分配得來的10和20字節的區域就在堆上 

} 

  

堆和棧的區別

申請方式

: 由系統自動分配。 例如,聲明在函數中一個局部變量 int b; 系統自動在棧中為b開辟空間

: 需要程序員自己申請,並指明大小,在c中malloc函數 如p1 = (char *)malloc(10); 在C++中用new運算符 如p2 = new char[10];

申請後系統的響應

:只要棧的剩余空間大於所申請空間,系統將為程序提供內存,否則將報異常提示棧溢出。

:首先應該知道操作系統有一個記錄空閑內存地址的鏈表,當系統收到程序的申請時,會遍歷該鏈表,尋找第一個空間大於所申請空間的堆結點,然後將該結點從空閑結點鏈表中刪除,並將該結點的空間分配給程序。 另外,對於大多數系統,會在這塊內存空間中的首地址處記錄本次分配的大小,這樣,代碼中的delete語句才能正確的釋放本內存空間。

申請大小的限制

:在Windows下,棧是向低地址擴展的數據結構,是一塊連續的內存的區域。這句話的意思是棧頂的地址和棧的最大容量是系統預先規定好的,如果申請的空間超過棧的剩余空間時,將提示overflow。因此,能從棧獲得的空間較小。

:堆是向高地址擴展的數據結構,是不連續的內存區域。這是由於系統是用鏈表來存儲的空閑內存地址的,自然是不連續的,而鏈表的遍歷方向是由低地址向高地址。堆的大小 受限於計算機系統中有效的虛擬內存。堆獲得的空間比較靈活,也比較大。

申請效率的比較

棧:由系統自動分配,速度較快。但程序員是無法控制的。

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

幾種分配方式的內存生命期

靜態分配的區域的生命期是整個軟件運行期,就是說從軟件運行開始到軟件終止退出。只有軟件終止運行後,這塊內存才會被系統回收。

在棧中分配的空間的生命期與這個變量所在的函數、類和Block(即由{}括起來的部分)相關。如果是函數中定義的局部變量,那麽它的生命期就是函數被調用時,如果函數運行結束,那麽這塊內存就會被回收。如果是類中的成員變量,則它的生命期與類實例的生命期相同。如果在Block中定義的局部變量,則它的生命期僅在Block內。

在堆上分配的內存,生命期是從調用new或者malloc開始,到調用delete或者free結束。如果不調用delete或者free,則這塊空間只有到軟件運行結束後才會被Windows系統回收。

內存分配方式