2012-01-24 25 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