初步了解
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ù)的二進制代碼
大致如圖所示



示例代碼:
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)會自動的將多余的那部分重新放入空閑鏈表中。
申請的限制是怎樣的?
- 棧:
棧是向低址擴展的數(shù)據(jù)結(jié)構(gòu),是一塊連續(xù)的內(nèi)存的區(qū)域。是棧頂?shù)牡刂泛蜅5淖畲笕萘渴窍到y(tǒng)預先規(guī)定好的,棧的大小是2M(也有的說是1M,總之是一個編譯時就確定的常數(shù)),如果申請的空間超過棧的剩余空間時,將提示overflow,因此,能從棧獲取的空間較小。
- 堆:
堆是向高地址擴展的數(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ā)出申請)、付錢、和吃(使用),吃完了就走,不用理會切菜,洗菜等準備工作和洗完、刷鍋等掃尾工作。他的好處是快捷,但是自由度比較小。
使用堆就像是自己動手做喜歡吃的菜肴,比較麻煩,但是比較符合自己的口味,而且自由度大。