多線程與內(nèi)存管理讀書摘錄(引用計(jì)數(shù)ARC篇)

一.內(nèi)存管理的思考方式

1.引用計(jì)數(shù)的思考方式:

  • 自己生成的對象丑慎,自己持有
  • 非自己生成的對象移剪,自己也能持有
  • 不再需要自己持有的對象時釋放
  • 非自己持有的對象無法釋放
對象操作與Objective-C 方法的對應(yīng)
對象操作 Objcetive-C 方法
生成并持有對象 alloc/new/copy/mutableCopy 等方法
持有對象 retain
釋放對象 release
廢棄對象 dealloc

2.alloc/retain.release/dealloc 實(shí)現(xiàn)

GNUstep是Cocoa框架的互換框架究珊。理解了GNUstep源代碼也就相當(dāng)于理解了蘋果的Cocoa實(shí)現(xiàn)。

a.通過allocWithZone:類方法調(diào)用NSAllocateObject函數(shù)分配了對象纵苛。

b.NSAllocateObject函數(shù)通過調(diào)用NSZoneMalloc函數(shù)來分配存放對象所需的內(nèi)存空間剿涮,之后將改內(nèi)存空間置0,最后返回作為對象而使用的指針攻人。

c.NSZone:為防止內(nèi)存碎片化而引入的結(jié)構(gòu)

總結(jié):GNUstep中alloc/retain/release/dealloc 的實(shí)現(xiàn)
  • 在Objective-C的對象中存有引用計(jì)數(shù)這一整數(shù)值取试。
  • 調(diào)用alloc或是retain方法后,引用計(jì)數(shù)值加1
  • 調(diào)用release后怀吻,引用計(jì)數(shù)值減1
  • 引用計(jì)數(shù)值為0時瞬浓,調(diào)用dealloc方法廢棄對象
GNUstep的實(shí)現(xiàn) 蘋果的實(shí)現(xiàn)
將引用計(jì)數(shù)保存在對象占用內(nèi)存塊頭部的變量中 保存在引用計(jì)數(shù)表的記錄中
少量代碼即可完成 對象用內(nèi)存塊的分配無需考慮內(nèi)存塊頭部
能夠統(tǒng)一管理引用計(jì)數(shù)用內(nèi)存塊與對象用內(nèi)存塊 引用計(jì)數(shù)表各記錄中存有內(nèi)存快地址,可從各個記錄追溯到各對象的內(nèi)存塊

3.autorelease理解

定義:自動釋放蓬坡,當(dāng)對象實(shí)例超出作用域(相當(dāng)于變量作用域)時猿棉,對象實(shí)例的release實(shí)例方法被調(diào)用。

  • 生成并持有NSAutoreleasePool對象
  • 調(diào)用已分配對象的autorelease實(shí)例方法
  • 廢棄NSAutoreleasePool對象
autorelease實(shí)現(xiàn)
GNUstep的實(shí)現(xiàn) 蘋果的實(shí)現(xiàn)
atuorelease實(shí)例方法的本質(zhì)就是調(diào)用NSAutoreleasePool對象的addObject方法 通過objc4庫的runtime/objc-arr.mm 確認(rèn)autorelease實(shí)現(xiàn) 類似

4.ARC規(guī)則

A.所有權(quán)修飾符
  • __strong 修飾符
  • __weak 修飾符
  • __unsafe _unretained 修飾符
  • __autoreleasing 修飾符
1).__strong 修飾符

__strong 修飾符是id類型和對象類型默認(rèn)的所有權(quán)修飾符屑咳,表示對對象的“強(qiáng)引用”萨赁。持有強(qiáng)引用的變量在超出其作用域是被廢棄,隨著強(qiáng)引用的失效兆龙,引用的對象會隨之釋放杖爽。通過 _strong 修飾符,不必再次鍵入retain或者release,完美地滿足了 “引用計(jì)數(shù)式內(nèi)存管理的思考方式”紫皇。

2).__weak 修飾符

循環(huán)引用容易發(fā)生內(nèi)存泄露慰安。所謂內(nèi)存泄漏就是應(yīng)當(dāng)廢棄的對象在超出其生存周期后繼續(xù)存在

__weak 修飾符的一個優(yōu)點(diǎn):在持有某對象的弱引用時,若該對象被廢棄坝橡,則此弱引用將自動失效且處于nil被賦值的狀態(tài)(空弱引用)泻帮。

3).__unsafe _unretained 修飾符

__weak 修飾符只能用于iOS5 以上以及OS X Lion 以上版本的應(yīng)用程序,之下版本使用了 __unsafe _unretained 修飾符计寇。

__unsafe _unretained 是不安全的所有權(quán)修飾符锣杂,附有 __unsafe _unretained 修飾符的變量不屬于編譯器的內(nèi)存管理對象脂倦。

4).__autoreleasing 修飾符

ARC有效時

@autoreleasepool{
   id __autoreleasing obj = [[NSObject alloc] init];
}

指定“@autoreleasepool塊”來替代“NSAutoreleasePool類對象生成、持有以及廢棄”這一范圍元莫。

id的指針或?qū)ο蟮闹羔槙J(rèn)附加上__autoreleasing 修飾符

- (BOOL) performOperationWithError:(NSError **) error;
等同于
- (BOOL) performOperationWithError:(NSError * __autoreleaasing *) error;

賦值給對象指針是赖阻,所有權(quán)修飾符必須一致

///正確寫法
NSError *error = nil;
NSError *__strong *pError = &error;

了解@autoreleasepool

NSRunLoop等實(shí)現(xiàn)不論ARC有效還是無效,均能夠隨時釋放注冊到autoreleasepool中的對象

autoreleasepool 范圍以塊級源代碼表示踱蠢,提高了程序的可讀性火欧,所以今后在ARC無效時也推薦使用@autoreleasepool塊。


B.具體的ARC規(guī)則
  • 不能使用retain/release/retainCount/autorelease
  • 不能使用NSAllocateObject/NSDeallocateObject
  • 須遵守內(nèi)存管理的方法命名規(guī)則
  • 不要顯示調(diào)用dealloc
  • 使用@autoreleasepool塊替代NSAutoreleasePool
  • 不能使用區(qū)域(NSZone)
  • 對象型變量不能作為C語言結(jié)構(gòu)體(struct/union)的成員
  • 顯示轉(zhuǎn)換“id”和“void * ”
1).不能使用retain/release/retainCount/autorelease

設(shè)置ARC有效時茎截,無需(禁止)再次鍵入retain或release代碼

即使ARC被設(shè)置為無效時苇侵,該源代碼也完全不符合引用計(jì)數(shù)式內(nèi)存管理的思考方式。

2).不能使用NSAllocateObject/NSDeallocateObject
3).須遵守內(nèi)存管理的方法命名規(guī)則
  • alloc
  • new
  • copy
  • mutableCopy
  • init(ARC有效時企锌,更嚴(yán)格榆浓,改方法必須是實(shí)例方法,并且必須要返回對象撕攒,返回的對象應(yīng)為id類型或該方法聲明類的對象類型陡鹃,抑或是該類的超類或子類型)
雖然以init開始的方法但并不包含在上述命名規(guī)則里
 - (void) initialize;
4).不要顯示調(diào)用dealloc

deallo方法在大多數(shù)情況下適用于刪除已注冊的代理或觀察者對象

5).使用@autoreleasepool塊替代NSAutoreleasePool
6).不能使用區(qū)域(NSZone)

區(qū)域在現(xiàn)在的運(yùn)行時系統(tǒng)已經(jīng)單純地被忽略

7).對象型變量不能作為C語言結(jié)構(gòu)體(struct/union)的成員
struct data{
   NSMutableArray *array;
};
error: ARC forbids Objective-C objs in structs or unions
NSMutableArray *array;

要把對象型變量加入到機(jī)構(gòu)提成員中時,可強(qiáng)制轉(zhuǎn)換為 void * 或是附加 __unsafe _unretained 修飾符

struct Data{
      NSMutableArray __unsafe_unretained *array;
};
附有 __unsafe_unretained 修飾符的變量不屬于編譯器的內(nèi)存管理對象
8).顯示轉(zhuǎn)換“id”和“void * ”

__bridge 轉(zhuǎn)換

  • 安全性與賦值低抖坪,容易因?yàn)閼掖怪羔樁鴮?dǎo)致程序奔潰
  • 還有__bridge_retained 與 __bridge_transfer兩種轉(zhuǎn)換
  • 在Objective-C對象與Core Foundation 對象之間相互變換
屬性
屬性聲明的屬性 所有權(quán)修飾符
assign __unsafe _unretained 修飾符
copy(不是簡單的賦值萍鲸,它賦值的是通過NSCopying接口的copyWithZone:方法賦值源所生成的對象 __strong 修飾符 (賦值的是被復(fù)制的對象)
retain __strong 修飾符
strong __strong 修飾符
unsafe_unretained __unsafe _unretained
weak __weak 修飾符
數(shù)組

在分配內(nèi)存時推薦使用calloc函數(shù)

C. ARC的實(shí)現(xiàn)

ARC由以下工具、庫來說實(shí)現(xiàn)

  • clang (LLVM編譯器)3.0以上
  • objc4 Objective-C 運(yùn)行時庫 493.9以上

__strong修飾符

objc_retainAutoreleasedReturnValue objc_autoreleaseReturnValue
alloc/new/copy/mutableCopy之外類方法等返回對象的實(shí)現(xiàn)上 alloc/new/copy/mutableCopy

__weak修飾符 [重點(diǎn)]

  • 若附有__weak 修飾符的變量所引用的對象被廢棄擦俐,則將nil賦值給該變量
  • 使用附有__weak 修飾符的變量脊阴,即是使用注冊到autoreleasepool中的對象
 {
  id __weak obj1 = obj;
 }

 /* 編譯器模擬代碼*/
 id obj1;
 objc_initWeak(&obj1,obj);
 objc_destoryWeak(&obj1);
 *******
 obj1 = 0;
 objc_storeWeak(&obj1,obj);
  *******

objc_storeWeak 函數(shù)把第二參數(shù)的賦值對象的地址作為鍵值,將第一參數(shù)的附有__weak修飾符的變量的地址注冊到weak表中蚯瞧。如果第二參數(shù)為 0蹬叭,則把變量的地址從weak表中刪除。weak表與引用計(jì)數(shù)表相同状知,作為散列表被實(shí)現(xiàn)秽五。

釋放對象,程序的動作:

  • objc_release
  • 引用計(jì)數(shù)為0饥悴,執(zhí)行dealloc
  • _ objc _rootDealloc
  • object_dispose
  • objc_destructInstance
  • objc_clear_deallocating

objc _clear _deallocating的函數(shù)動作

1.從weak表中獲取廢棄對象的地址為鍵值的記錄
2.將包含在記錄中的所有附有__weak修飾符變量的地址坦喘,賦值為nil
3.從weak表中刪除該記錄
4.從引用計(jì)數(shù)表中刪除廢棄對象的地址為鍵值的記錄

只在需要避免循環(huán)引用時使用__weak修飾符,否則會消耗相應(yīng)的CPU資源

__autoreleasing修飾符

引用計(jì)數(shù)

{
   id __strong obj = [[NSObject alloc] init];
   NSLog(@"retain count = %d",_objc_rootRetainCount(obj));
}

實(shí)際上并不能夠完全信任_objc_rootRetainCount函數(shù)取得的數(shù)值西设。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末瓣铣,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子贷揽,更是在濱河造成了極大的恐慌棠笑,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,590評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件禽绪,死亡現(xiàn)場離奇詭異蓖救,居然都是意外死亡洪规,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,157評論 3 399
  • 文/潘曉璐 我一進(jìn)店門循捺,熙熙樓的掌柜王于貴愁眉苦臉地迎上來斩例,“玉大人,你說我怎么就攤上這事从橘∧罡希” “怎么了?”我有些...
    開封第一講書人閱讀 169,301評論 0 362
  • 文/不壞的土叔 我叫張陵恰力,是天一觀的道長叉谜。 經(jīng)常有香客問我,道長踩萎,這世上最難降的妖魔是什么正罢? 我笑而不...
    開封第一講書人閱讀 60,078評論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮驻民,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘履怯。我一直安慰自己回还,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,082評論 6 398
  • 文/花漫 我一把揭開白布叹洲。 她就那樣靜靜地躺著柠硕,像睡著了一般。 火紅的嫁衣襯著肌膚如雪运提。 梳的紋絲不亂的頭發(fā)上蝗柔,一...
    開封第一講書人閱讀 52,682評論 1 312
  • 那天,我揣著相機(jī)與錄音民泵,去河邊找鬼癣丧。 笑死,一個胖子當(dāng)著我的面吹牛栈妆,可吹牛的內(nèi)容都是我干的胁编。 我是一名探鬼主播,決...
    沈念sama閱讀 41,155評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼鳞尔,長吁一口氣:“原來是場噩夢啊……” “哼嬉橙!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起寥假,我...
    開封第一講書人閱讀 40,098評論 0 277
  • 序言:老撾萬榮一對情侶失蹤市框,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后糕韧,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體枫振,經(jīng)...
    沈念sama閱讀 46,638評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡喻圃,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,701評論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了蒋得。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片级及。...
    茶點(diǎn)故事閱讀 40,852評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖额衙,靈堂內(nèi)的尸體忽然破棺而出饮焦,到底是詐尸還是另有隱情,我是刑警寧澤窍侧,帶...
    沈念sama閱讀 36,520評論 5 351
  • 正文 年R本政府宣布县踢,位于F島的核電站,受9級特大地震影響伟件,放射性物質(zhì)發(fā)生泄漏硼啤。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,181評論 3 335
  • 文/蒙蒙 一斧账、第九天 我趴在偏房一處隱蔽的房頂上張望谴返。 院中可真熱鬧,春花似錦咧织、人聲如沸嗓袱。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,674評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽渠抹。三九已至,卻和暖如春闪萄,著一層夾襖步出監(jiān)牢的瞬間梧却,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,788評論 1 274
  • 我被黑心中介騙來泰國打工败去, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留放航,地道東北人。 一個月前我還...
    沈念sama閱讀 49,279評論 3 379
  • 正文 我出身青樓圆裕,卻偏偏與公主長得像三椿,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子葫辐,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,851評論 2 361

推薦閱讀更多精彩內(nèi)容