iOS:ARC內(nèi)存管理知識(shí)總結(jié)(一)

1. ARC的基本概念

  • 在objc中采用automatic reference counting 機(jī)制, 讓編譯器來進(jìn)行內(nèi)存管理。在降低程序崩潰,內(nèi)存管理泄漏等風(fēng)險(xiǎn)的同時(shí),很大程度減少了程序員的工作量。
    -------摘自蘋果發(fā)開者文檔

  • 自動(dòng)引用計(jì)數(shù)的思維方式:

  • 自己生成的對(duì)象,自己持有。

  • 非自己生成的對(duì)象,自己也能持有。

  • 再需要自己持有對(duì)象時(shí)釋放。

  • 非自己持有的對(duì)象無法釋放。

  • 對(duì)象操作與OBJC方法的對(duì)應(yīng)。

  • 生成并持有對(duì)象 ------ alloc/new/copy/mutableCopy(這些方法意味著自己生成的對(duì)象只能自己持有)

  • 持有對(duì)象 ------ retain

  • 釋放對(duì)象 ------ release

  • 銷毀對(duì)象 ------ dealoc

  • 非自己生成的對(duì)象,自己也能持有

/*取得的對(duì)象存在,但自己不持有對(duì)象*/
       id obj = [NSMutableArray array]//取得非自己生成的對(duì)象
       [obj retain]//自己持有對(duì)象
  • 對(duì)幾種內(nèi)存情況的總結(jié)
    • alloc/new/copy/mutableCopy這些方法自己生成且持有。
  • 如果是array等方法生成的對(duì)象不是自己持有的,但是可以通過調(diào)用retain方法變成自己持有。
  • 如果對(duì)自己生成且持有的對(duì)象使用```autorelease```方法,可以是對(duì)象存在但自己不持有。如:
    
id obj = [[obj alloc] init];
      [obj autorealease];
/*取得對(duì)象存在,但自己不持有*/
-  objc中,```array```等生成對(duì)象但自己不持有的方法內(nèi)部是通過```autorealease```方法實(shí)現(xiàn)的。

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

  • alloc方法的內(nèi)部實(shí)現(xiàn):
    alloc方法內(nèi)部調(diào)用的是allocWithZone:(NSDefaultZone())這個(gè)對(duì)象方法。該方法又調(diào)用了NSAllocateObject()函數(shù)。所以在這里只需關(guān)注該方法即可。
    該方法內(nèi)部如下:
struct obj_layout
{
    NSInteger retained;
};
inline id 
NSAllocateObject(Class aClass,NSInteger extraBytes,NSZone *zone){
    int size = 計(jì)算容納對(duì)象所需內(nèi)存大小;
    id new = NSZoneMalloc(zone,size);
    memset (new,0,size);
    new = (id) & ((struct obj_layout *) new)[1];

}
  • 該函數(shù)將該內(nèi)存空間置為0(包括 obj_layout這個(gè)結(jié)構(gòu)體),且返回一個(gè)作為對(duì)象而使用的指針。

該內(nèi)存空間內(nèi)部,也就是對(duì)象所處的內(nèi)存空間內(nèi)部,頭部是struct obj_layout這個(gè)結(jié)構(gòu)體,接下來才是對(duì)象。alloc方法返回的指針指向的頭部以下的內(nèi)容。也就是除去結(jié)構(gòu)體的內(nèi)容。

可以通過查看retainCount這個(gè)方法的源代碼驗(yàn)證以上結(jié)論:

- (NSUInteger)retainCout{
    return NSExtraRefcount(self)+1;//需要注意此處的+1,對(duì)象內(nèi)存的頭部結(jié)構(gòu)體里的retain其實(shí)為0,所以+1。
}

inline NSUInteger 
NSExtraRefcount(id anObject){
    return((struct obj_layout *) anObject)[-1].retained;//此處需要注意-1,因?yàn)橐L問的實(shí)質(zhì)對(duì)象所處內(nèi)存空間的頭部,也就是結(jié)構(gòu)體obj_layout.
}

3.retain,release即delloc方法的實(shí)現(xiàn)。

無論是retain還是release,其實(shí)內(nèi)部都是通過操作對(duì)象所處內(nèi)存空間頭部的結(jié)構(gòu)體來實(shí)現(xiàn)的。

  • retain:
((struct obj_layout *) anObject)[-1].retained++;
  • release:這個(gè)方法的內(nèi)部實(shí)現(xiàn)稍微要比retain復(fù)雜一點(diǎn),是因?yàn)橐袛嘁糜?jì)數(shù)是否為0,如果為0 則需要銷毀對(duì)象(即調(diào)用dealloc方法)
- (void)release{
    if(NSDecrementExtraRefCountWasZero(self)){
        [self dealloc];
    }
}
BOOL
NSDecrementExtraRefCountWasZero(id anObject){
    if (obj_layout結(jié)構(gòu)體內(nèi)部的retained是否為0)
    {
        若為0,返回yes
    }else{
        返回no
    }
}
  • delloc方法:調(diào)用NSDellocatteObject()函數(shù),其內(nèi)部freestruct objc_layout結(jié)構(gòu)體。
    以上即是alloc,release,retain,delloc方法在GNUstep的實(shí)現(xiàn),*總結(jié)如下:
    1.在Objective-C的對(duì)象中存在引用計(jì)數(shù)這一數(shù)值;
    2.調(diào)用alloc,retain方法后,引用計(jì)數(shù)+1;
    3.引用計(jì)數(shù)為0時(shí),調(diào)用delloc方法銷毀對(duì)象。
最后編輯于
?著作權(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)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

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