iOS中的堆(heap)和棧(stack)的理解

操做系統iOS 中應用程序使用的計算機內存不是統一分配空間,運行代碼使用的空間在三個不一樣的內存區域,分紅三個段:「text segment 「,「stack segment 」,「heap segment 」。 函數

段「text segment 」是應用程序運行時應用程序代碼存在的內存段。每個指令,每個單個函數、過程、方法和執行代碼都存在這個內存段中直到應用程序退出。通常狀況下,你不會真的不得不知道這個段的任何事情。 操作系統

當應用開始之後,函數main() 被調用,一些空間分配在」stack」 中。這是爲應用分配的另外一個段的內存空間,這是爲了函數變量存儲須要而分配的內存。每一次在應用中調用一個函數,「stack 」的一部分會被分配在」stack」 中,稱之爲」frame」 。新函數的本地變量分配在這裏。 指針

正如名稱所示,「stack 」是後進先出(LIFO )結構。當函數調用其餘的函數時,「stack frame 」會被建立;當其餘函數退出後,這個「frame 」會自動被破壞。 對象

 「heap」 段也稱爲」data」 段,提供一個保存中介貫穿函數的執行過程,全局和靜態變量保存在「heap」中,直到應用退出。 生命週期

爲了訪問你建立在heap 中的數據,你最少要求有一個保存在stack 中的指針,由於你的CPU 經過stack 中的指針訪問heap 中的數據。 內存

你能夠認爲stack 中的一個指針僅僅是一個整型變量,保存了heap 中特定內存地址的數據。實際上,它有一點點複雜,但這是它的基本結構。 it

 

簡而言之,操做系統使用stack 段中的指針值訪問heap 段中的對象。若是stack 對象的指針沒有了,則heap 中的對象就不能訪問。這也是內存泄露的緣由。 內存管理

在iOS 操做系統的stack 段和heap 段中,你均可以建立數據對象。 table

stack 對象的優勢主要有兩點,一是建立速度快,二是管理簡單,它有嚴格的生命週期。stack 對象的缺點是它不靈活。建立時長度是多大就一直是多大,建立時是哪一個函數建立的,它的owner 就一直是它。不像heap 對象那樣有多個owner ,其實多個owner 等同於引用計數。只有heap 對象纔是採用「引用計數」方法管理它。 變量

stack 對象的建立

只要棧的剩餘空間大於stack 對象申請建立的空間,操做系統就會爲程序提供這段內存空間,不然將報異常提示棧溢出。

heap 對象的建立

操做系統對於內存heap 段是採用鏈表進行管理的。操做系統有一個記錄空閒內存地址的鏈表,當收到程序的申請時,會遍歷鏈表,尋找第一個空間大於所申請的heap 節點,而後將該節點從空閒節點鏈表中刪除,並將該節點的空間分配給程序。

例如:

NSString 的對象就是stack 中的對象,NSMutableString 的對象就是heap 中的對象。前者建立時分配的內存長度固定且不可修改;後者是分配內存長度是可變的,可有多個owner, 適用於計數管理內存管理模式。

兩類對象的建立方法也不一樣,前者直接建立「NSString * str1=@"welcome"; 「,然後者須要先分配再初始化「 NSMutableString * mstr1=[[NSMutableString alloc] initWithString:@"welcome"]; 」。

相關文章
相關標籤/搜索