內(nèi)存管理之weak指針實(shí)現(xiàn)原理

property屬性可以設(shè)置為strong、weakunsafe_unretained,轉(zhuǎn)化為修飾成員變量就是__strong__weak、__unsafe_unretained,下面通過(guò)代碼看一下他們的區(qū)別。

NSLog(@"局部作用域開(kāi)始");
 {
   Person *person = [[Person alloc] init];
   NSLog(@"person對(duì)象%@", person);
}
NSLog(@"局部作用域結(jié)束");

*******************運(yùn)行結(jié)果**********************

OCTest[53157:13009869] 局部作用域開(kāi)始
OCTest[53157:13009869] person對(duì)象<Person: 0x600001e50600>
OCTest[53157:13009869] -[Person dealloc]
OCTest[53157:13009869] 局部作用域結(jié)束

這說(shuō)明局部變量person處了作用域就結(jié)束之后,就釋放了。

    __strong Person *person1;
NSLog(@"局部作用域開(kāi)始"); 
{
      Person *person = [[Person alloc] init];
      NSLog(@"person對(duì)象%@", person);
      person1 = person;
}
NSLog(@"局部作用域結(jié)束");
NSLog(@"strongPerson:%@", person1);

*******************運(yùn)行結(jié)果**********************
OCTest[54823:13020229] 局部作用域開(kāi)始
OCTest[54823:13020229] person對(duì)象<Person: 0x600001308530>
OCTest[54823:13020229] 局部作用域結(jié)束
OCTest[54823:13020229] strongPerson:<Person: 0x600001308530>
OCTest[54823:13020229] -[Person dealloc]

當(dāng)person被作用域外的__strong指針指向時(shí),可以看到臨時(shí)作用域結(jié)束之后,person對(duì)象并沒(méi)有被銷(xiāo)毀,說(shuō)明__strong指針增加了person的引用計(jì)數(shù)。

__weak Person *person2;
NSLog(@"局部作用域開(kāi)始");
{        
    Person *person = [[Person alloc] init];
    NSLog(@"person對(duì)象%@", person);
    person2 = person;
}
NSLog(@"局部作用域結(jié)束");    
NSLog(@"weakPerson:%@", person2);

*******************運(yùn)行結(jié)果**********************
OCTest[55744:13025923] 局部作用域開(kāi)始
OCTest[55744:13025923] person對(duì)象<Person: 0x600002d505f0>
OCTest[55744:13025923] -[Person dealloc]
OCTest[55744:13025923] 局部作用域結(jié)束
OCTest[55744:13025923] weakPerson:(null)

這說(shuō)明當(dāng)person被作用域外的__weak指針指向時(shí),可以看到臨時(shí)作用域結(jié)束之后,person和第一種情況一樣,直接釋放了,說(shuō)明__weak指針沒(méi)有增加person的引用計(jì)數(shù),并且,person釋放時(shí)候,__weak指針被置為nil,防止了野指針錯(cuò)誤。

    NSLog(@"局部作用域開(kāi)始");
    {
        Person *person = [[Person alloc] init];
        NSLog(@"person對(duì)象%@", person);
        person3 = person;
    }
    NSLog(@"局部作用域結(jié)束");
    NSLog(@"unsafe_unretainedPerson:%@", person3);
image.png

說(shuō)明當(dāng)person被作用域外的__unsafe_unretained指針指向時(shí),可以看到臨時(shí)作用域結(jié)束之后,person和第一種情況一樣,直接釋放了,說(shuō)明__unsafe_unretained指針也沒(méi)有增加person的引用計(jì)數(shù),但是最后卻出現(xiàn)了EXC_BAD_ACCESS報(bào)錯(cuò),說(shuō)明是野指針問(wèn)題。

從這里可以看出【__weak__unsafe_unretained的區(qū)別就是__weak會(huì)在對(duì)象被釋放的時(shí)候自動(dòng)置為nil,__unsafe_unretained不會(huì),會(huì)造成野指針問(wèn)題。】

那么當(dāng)一個(gè)對(duì)象要釋放時(shí),被weak修飾的指針是如何置空的呢?
◆當(dāng)一個(gè)對(duì)象要釋放時(shí),會(huì)自動(dòng)調(diào)用dealloc,接下的調(diào)用軌跡是
◇ dealloc
◇ _objc_rootDealloc
◇rootDealloc
◇object_dispose
◇objc_destructInstance、free

image.png

weak的實(shí)現(xiàn)原理總結(jié)如下

  • 當(dāng)一個(gè)對(duì)象objweak指針指向時(shí),這個(gè)weak指針會(huì)以obj作為key,被存儲(chǔ)到sideTable類(lèi)的weak_table這個(gè)散列表上對(duì)應(yīng)的一個(gè)weak指針數(shù)組里面。
    當(dāng)一個(gè)對(duì)象objdealloc方法被調(diào)用時(shí),Runtime會(huì)以objkey,從sideTableweak_table散列表中,找出對(duì)應(yīng)的weak指針列表,然后將里面的weak指針逐個(gè)置為nil。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容