2013-04-20 71 views
10

我注意到在Objective-C與ARC以下啓用:弱屬性被設置爲在dealloc的,但酒店的伊娃無不是零

讓我們簡單的A類和autosynthesized弱財產

@interface A 
@property (nonatomic, weak) id refObject; 
@end 

@implementation A 
@end 

而且與第二的dealloc B類實現

@interface B 
@end 

@implementation B 
-(void) dealloc 
{ 
    NSLog(@"In dealloc"); 
} 
@end 

最後介於A類有以下幾點:

@implementation A 
... 
-(void) foo 
{ 
    B* b = [B new]; 
    self.refObject = b; 
    // Just use b after the weak assignment 
    // in order to not dealloc 'b' before assignement 
    NSLog(@"%@", b); 
} 
... 
@end 

如果我在[B dealloc]設置一個斷點,並檢查[A refObject]財產,我可以看到a.refObject是零,但a->_refObject不是零,點到「b」

任何想法,爲什麼出現這種情況?

+0

說不定什麼時候知道弱裁判應該被清除,但實例變量本身保持不變(和釋放,而現在它是一個懸擺指針)存取方法返回'nil'。 – 2013-04-20 16:05:45

+0

我認爲,在dealloc的對象仍然是有效的,但不會被刪除。例如,您可以從NSNotificationCenter註銷它並可以訪問其屬性。 – 2013-04-20 16:15:30

+0

「您可以訪問它」並不一定意味着它不釋放,但我可能是錯的。 – 2013-04-20 16:16:34

回答

22

簡短的回答:實例變量a->_refObject是(還)沒有零的-[B dealloc], 但每次訪問該弱指針是通過ARC運行時函數 如果釋放已經開始返回零完成。

龍答:通過設置觀察點,你可以看到a->_refObject是在 釋放過程結束設爲零。該堆棧跟蹤(當觀察點被擊中)看起來是這樣的:

frame #0: 0x00007fff8ab9f0f8 libobjc.A.dylib`arr_clear_deallocating + 83 
frame #1: 0x00007fff8ab889ee libobjc.A.dylib`objc_clear_deallocating + 151 
frame #2: 0x00007fff8ab88940 libobjc.A.dylib`objc_destructInstance + 121 
frame #3: 0x00007fff8ab88fa0 libobjc.A.dylib`object_dispose + 22 
frame #4: 0x0000000100000b27 weakdealloc`-[B dealloc](self=0x000000010010a640, _cmd=0x00007fff887f807b) + 151 at main.m:28 
frame #5: 0x0000000100000bbc weakdealloc`-[A foo](self=0x0000000100108290, _cmd=0x0000000100000e6f) + 140 at main.m:41 
frame #6: 0x0000000100000cf5 weakdealloc`main(argc=1, argv=0x00007fff5fbff968) + 117 at main.m:52 
frame #7: 0x00007fff8c0987e1 libdyld.dylib`start + 1 

object_dispose()-[NSObject dealloc]調用(如可在 http://www.opensource.apple.com/source/objc4/objc4-532/runtime/NSObject.mm可以看出)。

因此在-[B dealloc]a->_refObject不是nil(生成編譯器)的前[super dealloc]被調用。

所以問題依然存在:爲什麼a.refObject在那一點返回零?

原因是,對於每次訪問弱指針,ARC編譯器都會生成 調用objc_loadWeak()objc_loadWeakRetained()。從documentation

ID objc_loadWeakRetained(ID *對象)

如果對象被註冊爲__weak對象,並存儲到對象的最後一個值沒有>尚未釋放或開始釋放,保留該值並返回它。否則>返回null。

所以,即使a->refObject不是零在這一點上,通過objc_loadWeakRetained()訪問弱指針 (通過屬性訪問方法來實現),因爲B對象的釋放已經開始返回nil, 。調試器直接訪問a->refObject,不調用objc_loadWeak()

+0

Noce謝謝。我認爲,每一次微弱的指針訪問的編譯器添加objc_loadWeak但目前看來,是不是有情況 - > _ refObj – 2013-04-21 15:24:15

+0

@plamkata__:在* *編譯'增加objc_loadWeak [保留]'每個訪問'A-> refObject' ,只有* debugger *直接訪問伊娃。 – 2013-04-22 06:47:37

+0

具有完美的感覺。我的印象是,當我發現我使用的NSLog在dealloc方法傾倒伊娃這種行爲,這也正是我感到困惑。但實際上我沒有使用NSLog,而是調試器,所以你提到它直接訪問它。再次感謝您的幫助。 – 2013-04-22 20:36:58

相關問題