簡單理解內(nèi)存的幾大區(qū)域

初步了解

1.棧區(qū)

棧區(qū)(stack)由編譯器自動分配并釋放,存放的是函數(shù)的參數(shù)值,局部變量等,方法調(diào)用的實參也是保存在棧區(qū)的。地址從高到低分配。棧是系統(tǒng)數(shù)據(jù)結(jié)構(gòu),對應線程/進程是唯一的。優(yōu)點是快速高效,缺點是有限制,數(shù)據(jù)不靈活。由編譯器自動分配釋放。主要存放一些基本類型的變量和對象引用類型。

2.堆區(qū)

由程序員分配和釋放,如果程序員不釋放,可能會出現(xiàn)內(nèi)存泄露,程序結(jié)束的時候,可能會由操作系統(tǒng)回收,比如iOS中alloc都是存放在堆中,優(yōu)點是靈活方便,數(shù)據(jù)適應面廣泛,但是效率有一定降低,堆空間的分配總是動態(tài)的,不同堆分配的內(nèi)存無法互相操作。地址是從低到高分配。雖然程序結(jié)束的時候所有的數(shù)據(jù)空間都會被釋放回系統(tǒng),但是精確的申請內(nèi)存,釋放內(nèi)存匹配是良好程序的基本要素。主要存放用new構(gòu)造的對象和數(shù)組。

3.全局區(qū)(靜態(tài)區(qū))

全局變量和靜態(tài)變量是放在一起的,初始化的全局變量和靜態(tài)變量存放在一塊區(qū)域,未初始化的全局變量和靜態(tài)變量在相鄰的另一塊區(qū)域,程序結(jié)束后由系統(tǒng)釋放

注意:全局區(qū)又可分為未初始化全局區(qū):.bss段和初始化全局區(qū):data段。

舉例:int a;未初始化的
int a = 10 ;已初始化的。

4.文字常量區(qū)

存放常量字符串,程序結(jié)束后由系統(tǒng)釋放。

5.代碼區(qū)

存放函數(shù)的二進制代碼

大致如圖所示


image

image

示例代碼:

int a = 10; // 全局初始化區(qū)
char *p; //    全局未初始化區(qū)
 
main{
   int b; // 棧區(qū)
   char s[] = "abc" // 棧區(qū)
   char *p1; //    棧區(qū)
   char *p2 = "123456" 123456 在常量區(qū),p2在棧上
   static int c = 0; // 全局(靜態(tài))初始化區(qū)
    
   w1 = (char *)malloc(10);
   w2 = (char *)malloc(20);
   分配得來的10和20字節(jié)的區(qū)域就在堆區(qū)。
}

申請后的系統(tǒng)是如何響應的?

存儲每一個函數(shù)在執(zhí)行的時候都會向操作系統(tǒng)索要資源,棧區(qū)就是函數(shù)運行時的內(nèi)存,棧區(qū)的變量由編譯器負責分配和釋放,內(nèi)存隨著函數(shù)的運行分配,隨著函數(shù)的結(jié)束而釋放,由系統(tǒng)自動完成。

注意:只要棧的剩余空間大于所申請空間,系統(tǒng)將為程序提供內(nèi)存,否則將報異常提示棧溢出。

首先應該知道操作系統(tǒng)有一個記錄空閑內(nèi)存地址的鏈表,當系統(tǒng)收到程序的申請時,會遍歷該鏈表,尋找第一個空間大于所申請空間的堆結(jié)點,然后將該結(jié)點從空閑結(jié)點鏈表中刪除,并將該結(jié)點的空間分配給程序。由于找到的堆結(jié)點的大小不一定正好等于申請的大小,系統(tǒng)會自動的將多余的那部分重新放入空閑鏈表中。

申請的限制是怎樣的?

  1. 棧:

棧是向低址擴展的數(shù)據(jù)結(jié)構(gòu),是一塊連續(xù)的內(nèi)存的區(qū)域。是棧頂?shù)牡刂泛蜅5淖畲笕萘渴窍到y(tǒng)預先規(guī)定好的,棧的大小是2M(也有的說是1M,總之是一個編譯時就確定的常數(shù)),如果申請的空間超過棧的剩余空間時,將提示overflow,因此,能從棧獲取的空間較小。

  1. 堆:

堆是向高地址擴展的數(shù)據(jù)結(jié)構(gòu),是不連續(xù)的內(nèi)存區(qū)域。這是由于系統(tǒng)使用鏈表來存儲的空閑內(nèi)存地址的,自然是不連續(xù)的,而鏈表的遍歷方向是由低地址向高地址。堆的大小受限于計算機系統(tǒng)中有效的虛擬內(nèi)存,由此可見,堆獲得的空間比較靈活,也比較大。

低地址 ------------------> 高地址

代碼區(qū) - 常量區(qū) - 全局區(qū) - 堆區(qū) - 棧區(qū)

棧:由系統(tǒng)自動分配,速度較快,不會產(chǎn)生內(nèi)存碎片。

堆:是由alloc分配的內(nèi)存,速度比較慢,而且容易產(chǎn)生內(nèi)存碎片,不過使用起來最方便。

打個比喻來說:

使用棧就像去飯館里吃飯,只管點菜(發(fā)出申請)、付錢、和吃(使用),吃完了就走,不用理會切菜,洗菜等準備工作和洗完、刷鍋等掃尾工作。他的好處是快捷,但是自由度比較小。

使用堆就像是自己動手做喜歡吃的菜肴,比較麻煩,但是比較符合自己的口味,而且自由度大。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

  • Swift1> Swift和OC的區(qū)別1.1> Swift沒有地址/指針的概念1.2> 泛型1.3> 類型嚴謹 對...
    cosWriter閱讀 11,666評論 1 32
  • 喜歡的話記得點贊 一、內(nèi)存管理:移動設備的內(nèi)存及其有限,每一個APP所能占用的內(nèi)存是有限制的二、什么行為會增加AP...
    甘哲157閱讀 2,092評論 1 12
  • 一、溫故而知新 1. 內(nèi)存不夠怎么辦 內(nèi)存簡單分配策略的問題地址空間不隔離內(nèi)存使用效率低程序運行的地址不確定 關(guān)于...
    SeanCST閱讀 8,133評論 0 27
  • “text segment ”是應用程序運行時應用程序代碼存在的內(nèi)存段。每一個指令,每一個單個函數(shù)、過程、方法和執(zhí)...
    紫云夕月閱讀 7,409評論 4 20
  • 數(shù)據(jù)結(jié)構(gòu) 棧就像裝數(shù)據(jù)的桶或箱子它是一種具有后進先出性質(zhì)的數(shù)據(jù)結(jié)構(gòu),也就是說后存放的先取,先存放的后取。 這就如同...
    小李不木閱讀 1,578評論 0 0

友情鏈接更多精彩內(nèi)容