iOS 記憶體管理

2021-09-01 00:22:53 字數 2580 閱讀 1150

首先,我們來了解一下ios中物件的儲存機制,通常我們使用物件的方法是宣告乙個物件指標,這個物件指標是存放在棧區的,再讓這個棧區的物件指標指向物件,物件是存放在堆區的,也就是說這個物件指標(棧區)中存放著物件的位址(堆區)。

棧區一般用於存放區域性變數以及函式的引數,是由編譯器分配的,而堆區的記憶體則是程式執行過程中動態的分配和釋放的,也就是說物件的記憶體是程式執行過程中動態分配和釋放的,ios中通過引用計數來管理物件記憶體的分配與釋放。

oc語言使用引用計數來管理物件的記憶體,每乙個物件都對應有乙個計數器用來記錄這個物件被使用的情況,我們把這個計數器稱為引用計數。當建立乙個物件時,它的引用計數為1,如果有乙個新的指標指向這個物件則它的引用計數加1,如果該指標不再指向這個物件的引用計數減1。

引用計數是通過 alloc/retain/release/delloc 操作來實現的

//生成並持有物件,物件引用計數為1

nsobject *object = [[nsobject alloc] init];

nslog(@"%lu",(unsigned long)[object retaincount]);

//物件引用計數加1

[object retain];

nslog(@"%lu",(unsigned long)[object retaincount]);

//引用計數減1

[object release];

nslog(@"%lu",(unsigned long)[object retaincount]);

// [object release];//這裡再release引用計數就是0,會自動呼叫delloc方法銷毀物件

// nslog(@"%@",object);//物件已經銷毀,這裡再使用該物件就會出錯

上面**的執行結果

2018-11-14 21:27:56.209992+0800 mrc[2459:91153] 1

2018-11-14 21:27:56.210297+0800 mrc[2459:91153] 2

2018-11-14 21:27:56.210473+0800 mrc[2459:91153] 1

除了引用計數,ios還提供了 nsautoreleasepool——自動釋放池來管理記憶體。我們通過alloc和init方法初始化 nsautoreleasepool 物件,drain 方法廢棄這個物件,在 nsautoreleasepool 的生命週期內呼叫物件的autorelease方法,就可以讓 autoreleasepool 管理這個物件,它會將該物件加入當前自動釋放池,當 autoreleasepool 銷毀(也就是呼叫drain方法)的時候再釋放自動釋放池中的所有物件。

for (int i = 0; i < 10e5 * 2; i++) 

for (int i = 0; i < 10e5 * 2; i++)

執行上面兩段**我們會發現第乙個占用記憶體明顯比第二個的少,正是 nsautoreleasepool 的作用。

以上就是ios記憶體管理機制,但是現在我們不需要要手動管理記憶體,因為ios提供了arc來自動管理記憶體(arc環境下是不能顯示呼叫retain/release/delloc),arc就是自動引用計數,我們使用恰當的所有權修飾符(或屬性關鍵字)修飾物件,系統會根據修飾符對物件的引用計數進行相應的操作,並在合適的時候自動釋放物件。

屬性關鍵字用來修飾物件的屬性

雖然arc環境下系統會自動管理記憶體,但是有些情況下依舊需要使用到自動釋放池,在arc 環境下用 @autoreleaseool{} 代替 nsautoreleasepool 物件的初始化與銷毀,花括號範圍內就是這個自動釋放池的生命週期 ,下面我們來看幾個arc環境下使用 @autoreleaseool{} 的例子。

//**一

for (int i = 0; i < 10e5 * 2; i++)

}//**二

for (int i = 0; i < 10e5 * 2; i++)

分別執行上面兩段**,我們會發現**一的記憶體明顯小於**二,這正是因為**一使用了 @autoreleaseool{},當出了autoreleasepool的生命週期時會自動釋放掉該物件。

值得一提的是arc環境下系統會在適當的時候建立和銷毀自動釋放池來管理某些特定的物件(比如通過array方法初始化的可變陣列)。其中建立與銷毀的時機與 runloop 的執行狀態有關。

迴圈引用

在arc環境下會有迴圈引用的問題,當乙個物件自己持有自己或者兩個物件相互持有或者多個物件之間的引用形成環的時候就會導致相互持有,從而都不能釋放造成記憶體洩漏的問題,這個問題可以通過weak修飾符來解決weak修飾符可以達到引用但不持有物件的效果,而且會在指標所引用物件被廢棄的時候自動將該指標置nil。

不能管理core foundation物件

arc環境不會自動管理core foundation物件,我們需要手動管理core foundation 物件的記憶體或者通過__bridge、__bridge_retained、__bridge_transfer關鍵字進行core foundationd物件與oc物件的轉換,把core foundation 物件的記憶體管理權交給arc去處理。

ios記憶體管理

引用計數 每個物件有乙個與之相關的整數,稱作 引用計數器 或者 保留計數器 當某段 需要訪問乙個物件時,該段 會將物件的保留計數器 1,表示需要訪問這個物件 當結束對該物件的訪問時,保留計數器 1,表示它不在訪問該物件 當保留計數器為0時,物件被銷毀,所佔記憶體被系統收回。當使用new retain...

iOS記憶體管理

前提 1 以下是針對cocoa物件,不包括core foundation 2 cocoa物件都是用引用計數來跟蹤物件的記憶體使用情況的。3 在子類裡面父類先初始化和後釋放的原則。自己想下為什麼 棧空間和堆空間的區別。我們說的記憶體管理都是基於堆空間的,因為函式內的棧空間是由編譯器自己控制的。關於co...

IOS 記憶體管理

範圍 任何繼承了nsobject的物件,對基本資料型別無效 原理 每個物件內部都儲存了乙個與之相關聯的整數,稱為引用計數器 當使用alloc new或者copy建立乙個物件時,物件的引用計數器被設定為1 給物件傳送一條retain訊息,可以使引用計數器值 1 給物件傳送一條release訊息,可以使...