(NSError * __ strong *)魔术

时间:2012-01-24 21:14:09

标签: objective-c automatic-ref-counting

没有任何序言我想向你展示我在程序中遇到的问题,我评论了步骤以及我对这些步骤的看法。 (我没有包括@interface部分的简短性,它使用与@implementation中相同签名的相同方法

@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   

如果我理解正确的话,这个方法中只有一个对象,它明确地被释放,而不是自动释放或其他东西。

1 个答案:

答案 0 :(得分: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值。