OC內存管理

01 概述

1.內存中有五大區域,為什么只需要關心堆區?

1)堆區存的是對象,對象占的區域可能會很大
2)堆區的對象不會自動釋放,需要手動管理,如果不進行管理,那么會直到程序結束的時候才會釋放

2.什么時候釋放堆區的對象

1)當這個OC對象沒有"人"使用的時候,可以釋放
2)當這個OC對象有"人"使用的時候,千萬不要釋放
注意:"人"表示對象的使用者

3.如何判斷一個OC對象是否有人使用

1.每一個OC對象都有一個引用計數器(retainCount),表示對象的使用者的個數
2.每當創建一個新的對象,retainCount值默認是1
3.每當多一個人要使用對象的時候,retainCount+1
4.每當少一個人要使用對象的時候,retainCount-1
5.當retainCount=0的時候,系統會立即回收該對象,同時給對象發送dealloc消息

4.程序員如何控制retainCount值?

1.向對象發送release消息,讓對象的retainCount-1
2.向對象發送retain消息,讓對象的retainCount+1
3.向隊形發送retainCount消息,獲得對象的retainCount值
4.所謂的消息,其實就是對象的方法
所有和內存管理相關的成員變量以及方法,都是定義在NSObject類中的

5.內存管理的分類

1.MRC,手動引用計數,程序員需要手動管理對象的retainCount值,
2.ARC,自動引用計數,編譯器幫我們管理對象的retainCount值
3.ARC和MRC的關系

1.ARC是基于MRC的
2.ARC是編譯器特性,編譯器在編譯的時候,會在合適的位置,自動插入內存管理的代碼
3.ARC是2011年iOS5出現,是程序員的一大福音,省去了很多繁瑣的內存管理的工作
4.從Xcode6開始,新建的項目默認都是ARC的

6.MRC是ARC的底層原理

只有理解MRC才能更好的理解內存管理的原理

02 MRC程序

1.如何關閉ARC機制,把項目設置為MRC

在項目信息頁面,選擇BuildSettings,搜索auto,找到"A...R...C...",默認是YES,改成NO即可.
注意:如果在ARC環境下,不能使用內存管理的方法,否則編譯器會報錯.

2.為什么我們重寫dealloc方法的時候,需要在最后調用父類的dealloc方法?

重寫init方法的時候

1.父類的init方法實現默認有一些初始化對象時必須的操作
2.需要在父類init方法的基礎之上增加一些操作,這個時候需要先調用父類中init方法實現

重寫dealloc方法的時候

1.父類的dealloc方法實現中默認有一些對象釋放的是否必須的操作,一旦調用了NSObject類中dealloc方法的實現,那么對象就會被徹底的釋放
2.我們在對象徹底釋放之前可能還需要對對象做一些事情,比如說需要先釋放當前對象中特有一些內容,在完成這些操作之后,再調用父類中dealloc方法的實現

3.注意點:

1.重寫dealloc方法的時候,必須在最后調用父類中dealloc方法的實現(MRC)
2.dealloc方法不需要手動調用,當對象銷毀的時候系統會自動調用該對象的dealloc方法,千萬不要手動調用
3.對象調用release方法之后就會銷毀嗎?
不一定,release方法只會讓當前對象的引用計數器-1,和銷毀對象之間沒有什么必然聯系

在MRC中判斷對象是否銷毀只有一個原則,就是對象的引用計數器是否為0

03 內存管理的原則

1.保持平衡

1.有new\alloc,就必須要有release
2.有retain,就必須要有release
3.誰new\alloc,誰release
4.誰retain,誰release

// 2.使用哪個指針給對象發送了new/alloc消息,就需要通過這個指針發送release
// 3.使用哪個指針個對象發送了retain消息,就需要通過這個指針發送release

Person *p1 = [[Person alloc] init];  //1
//[p1 release];

//Person *p2 = p1;
//[p2 retain];
// retain內部把當前對象的retainCount+1,然后返回當前對象

Person *p2 = [p1 retain];  // 2

[p1 release] // 1
[p2 release] // 0 -> 由系統調用dealloc方法,釋放對象

//
//Person *p2 = [p1 retain];
//Person *p3 = p1;
//
//[p1 release];
//[p2 release];

04 野指針與僵尸對象

在OC中

1.對象的回收

1.一旦對象回收,說明對象在內存中占有的堆區空間,可以分配給別人使用(不代表空間被刪掉,也不代表立刻分配給被人使用)
2.但是在系統把該空間分配給其他人使用之前,對象還存在(對象中的數據還存在)

2.僵尸對象

對象已經被回收了,但是對象的數據還存在內存中,這樣的對象叫做僵尸對象

注意點:

1.當僵尸對象占用的空間,系統沒有分配給其他人使用的時候,這個對象其實還存在,還可以訪問
2.當僵尸對象占用的空間,系統已經分配給其他人使用的時候,這個對象不存在,不可以訪問
3.嚴格意義上來說,對象一旦成為了僵尸對象,無論如何不能訪問
4.僵尸對象無法復活(不應該調用僵尸對象的方法)

Xcode中開啟僵尸對象檢測

默認沒有開啟,避免浪費性能
Edit Scheme -> Diagnostics -> 勾選Enable Zombie Object

3.野指針

指向被回收對象的指針,叫做野指針
指向堆區僵尸對象的棧區指針變量,叫做野指針

4.如何防止野指針錯誤
Person *p1 = [[Person alloc] init]; // 1
[p1 release] // 0
// p1是一個野指針,p1指向的堆區對象是僵尸對象
p1 = nil;

[nil sayHi];

05 單個對象的內存管理

int main() {
    Person *p1 = [Person new];
}
1.如何避免內存泄漏

1.retain和release一定要匹配
2.不要讓指針隨便指向nil

06 多個對象的內存管理之一

1.當對象A中擁有一個成員變量是對象B,如果A沒有釋放,那么B就不能是釋放.因為B作為A的成員變量,說明A隨時都有可能使用B,那么必須當A釋放的時候,才能把B釋放.

演化步驟:

1.創建對象A, 創建對象B
2.把B對象設置給A對象,
出現的問題:當B對象釋放之后,A對象就無法再使用B對象

解決方案:

3.在把B對象設置給A的時候,讓B對象的引用計數器+1,說明A對象擁有B對象
出現的問題:當A對象釋放之后,B對象無法釋放
解決方案:
4.當A對象銷毀的時候,也就是在A對象的dealloc方法中,先讓B對象的引用計數器-1,再釋放A對象

07 多個對象的內存管理之二

出現的問題:

如果給A類對象a中的B類型的成員變量更換了一個值,從b對象換成了b1,此時在a對象銷毀的時候,釋放的是b1,而無法釋放b,導致b內存泄漏

解決方案:

5.在B類型成員變量的set方法中,先release舊對象b,再retain新對象b1

08 回收分析

兩個A類型的不同對象a和a1,同時擁有一個B類型的成員和變量b,沒有出現任何問題

09 多個對象的內存管理之三

出現的問題:

如果給A類對象a中的B類型成員變量重復賦同一個值,之前是b,再賦一次b
因為在B類型的成員變量set方法中,是先release再retain,此時有可能導致b對象在release之后已經釋放,變成僵尸對象,再進行retain操作會造成野指針錯誤

解決方案:

6.在B類型成員變量的set方法中,需要進行判斷,如果是相同對象什么都不做,如果不是相同對象,先release舊對象,再retain新對象.

- (void)setB:(B *)b {
    if (_b != b) {
        [_b release];
        _b = [b retain];
    }
}

- (void)dealloc {
    [_b release];
    [super dealloc];
}

10 當屬性的類型是OC對象的時候,setter方法的寫法

注意:

當成員變量是OC對象的時候,它的set方法才需要按照以上總結的內容來寫.
當成員變量是基本數據類型的時候,直接賦值即可.

11 @property參數之與多線程相關的

多線程相關

  1. atomic(默認值) 安全的
  1. nonatomic 不安全的

12 @property參數之與生成setter方法實現相關的

在MRC下和內存管理相關的參數

assign(默認)
retain
如果成員變量是OC對象,使用retain
如果成員變量是非OC對象,使用assign

13 @property其他參數

1.讀寫相關的

1.readwrite(默認),可讀可寫,會同時生產getter和setter
2.readonly,只讀,只會生產getter,而不會生成setter

2.指定setter和getter名字

注意:

1.如果需要設置setter的名字,一定要加:.但是無論如何都不要更改setter的名字
2.如果成員變量是BOOL類型,getter一般以is開頭,增加可讀性
3.只是改變了setter和getter的名字,并沒有改變內部實現

14 @property參數使用注意

1.在使用@property的時候,必須要加參數

1.每種類型的參數,同時只能存在一個
2.至少需要兩類:線程相關的,內存管理相關的
規范寫法:@property (nonatomic, retain) NSString *name;

2.如果在MRC環境下

當使用@property定義屬性的時候,如果使用reatin,只會在setter中生成標準的MRC內存管理代碼
但是dealloc中對該成員變量,并沒有release,需要我們自己來做

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,460評論 6 538
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,067評論 3 423
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,467評論 0 382
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,468評論 1 316
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,184評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,582評論 1 325
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,616評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,794評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,343評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,096評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,291評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,863評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,513評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,941評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,190評論 1 291
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,026評論 3 396
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,253評論 2 375

推薦閱讀更多精彩內容

  • 今天看到一篇不錯的文章關于OC內存管理的,轉載一下與你共享概述我們知道在程序運行過程中要創建大量的對象,和其他高級...
    niceSYT閱讀 458評論 0 2
  • 內存管理 簡述OC中內存管理機制。與retain配對使用的方法是dealloc還是release,為什么?需要與a...
    丶逐漸閱讀 1,986評論 1 16
  • OC內存管理一、基本原理(一)為什么要進行內存管理。由于移動設備的內存極其有限,所以每個APP所占的內存也是有限制...
    ScaryMonsterLyn閱讀 527評論 0 3
  • ARC 一、簡介 在Objective-C中采用Automatic Reference Counting (ARC...
    伶俐ll閱讀 1,666評論 0 3
  • 如果能再見你一面 我想被你擁入懷中 不想聽你說好久不見 你應該說 我一直在等你 那么 我來了 你在哪? 時間是一名...
    好夢從未成真閱讀 534評論 0 0