2012-01-24 23 views
1

沒有任何序言我想告訴你我在我的程序中遇到的問題,我評論了步驟和我對這些步驟的想法。 (我沒有包括@interface一部分急促,它具有相同簽名相同的方法@implementation(NSError * __ strong *)magic

@implementation Dummy 

- (int)testing:(NSError *__strong *)error 
{ 
    *error = [[NSError alloc] initWithDomain:@"hello" code:42 userInfo:nil]; 
    // 3. retain count = 1 

    // 4. because of ARC 'error' object was released for this time 
    // (assembly output is my proof) object is deallocated 
    // retain count = 0 

    return 0; 
} 

@end 

int main() 
{ 
    NSError *e = nil; // 1. retain count = 0 (obviously) 
    Dummy *dummy = [[Dummy alloc] init]; 

    [dummy testing:&e]; // 2. passing reference to an error object 

    // 'e' for this time has to be just a trash, or nil maybe, 
    // but next log gives me correct output: 
    NSLog(@"%@ %li", [e domain], [e code]); // 'hello 42' 

    return 0; 
} 

怎樣一個錯誤的對象後,死亡的存在嗎?我明白,使用NSError *__autoreleasing *將是正確的路,在這種情況下情況將變得微不足道,但編譯器如何推理此代碼,我的錯誤在哪裏判斷?

這是一個有點人爲的問題,但我不能從我的頭上拋出這種情況,我想我失去了一些東西。

這裏是-[Dummy testing:]

callq 0x100000e8c <dyld_stub_objc_msgSend> 
mov -0x18(%rbp),%rcx 
mov (%rcx),%rdx 
mov %rax,(%rcx) 
mov %rdx,%rdi 
callq 0x100000e92 <dyld_stub_objc_release> 
mov -0x24(%rbp),%eax 
add $0x40,%rsp 
pop %rbp 
retq 

拆卸的一部分。如果我理解正確的,只有一個在這個方法的對象,而且它顯然釋放,而不是自動釋放或別的東西。

+0

順便說一下,在ARC下,所有的對象堆棧變量都被初始化爲nil,所以你不需要在聲明'NSError * e'時說'= nil'。 –

回答

3

我懷疑你對發佈的內容感到困惑。我剛剛檢查了彙編輸出,並且有一個致電objc_release()的調用,但我對x86彙編不夠熟悉,無法準確跟蹤發生了什麼。不過,我知道這裏的代碼應該發出的等價的東西:

NSError *temp = [[NSError alloc] initWithDomain:@"hello" code:42 userInfo:nil]; 
[*error release]; 
*error = [temp retain]; 
[temp release]; 

,當然還有優化器將收縮,要

NSError *temp = ... 
[*error release]; 
*error = temp; 

所以我覺得你看到對objc_release()的呼叫,並認爲你新分配的錯誤正在釋放。不是。之前的值*error將在新分配的錯誤放入該位置之前釋放。

+0

有趣的是,我可以在哪裏閱讀有關編譯器的這種行爲?我想如果對象給出的對象是強壯的,它會被保留下來(在這個例子中保留爲零),然後釋放(釋放實際對象後)。 – goodfella

+1

@goodfella:不太確定你的意思。在ARC下,當寫入__strong位置時,該位置的前一個值被釋放,新值被保留。這會產生你在我的答案中看到的代碼片段。現在,如果優化器可以證明保留/釋放對是不必要的,它可以刪除它們,這會導致我的代碼片段稍短。無論如何,在這種情況下,alloc'd錯誤不會在'-testing:'內部釋放,因爲它的存儲位置不會超出範圍。 –

+0

我迷惑自己對象所有權政策和「通過引用返回」的情況,無法將它們集合在一起,謝謝澄清。 – goodfella