为什么将正在进行释放的对象设置为弱属性会导致崩溃

时间:2016-03-14 15:18:27

标签: objective-c clang automatic-ref-counting weak-references dealloc

Clang's Objective-C Automatic Reference Counting中,我们看到以下内容

  

对于__weak对象,左值更新为指向新的指针,除非新指针是当前正在进行解除分配的对象,在这种情况下,左值更新为空指针。这必须相对于对象的其他赋值,从对象读取以及新指针的最终版本以原子方式执行。

objc-weak.mm中,我们会看到weak_register_no_lock()中的以下代码块:

    if (deallocating) {
    if (crashIfDeallocating) {
        _objc_fatal("Cannot form weak reference to instance (%p) of "
                    "class %s. It is possible that this object was "
                    "over-released, or is in the process of deallocation.",
                    (void*)referent, object_getClassName((id)referent));
    } else {
        return nil;
    }
}

我在我的UIViewController子类dealloc方法中设置了一个断点,并尝试在lldb中调用[self allowsWeakReference],这导致NO值。

如果我们尝试将self设置为另一个对象的weak属性,应用程序将根据objc-weak.mm代码崩溃。

问题是 - 为什么会这样?铿锵的规格是错的吗?这是objc实现中的错误吗?

这是一段简单的代码,可以重现崩溃:

//cc -fmodules -fobjc-arc -g crash.m -o crash
@import Foundation;

@interface Foo : NSObject
@end

@implementation Foo
- (void)dealloc {
  Foo * __weak weakSelf = self; // crashes on this line
}
@end

int main() {
  (void)[[Foo alloc] init];
  return 0;
}

1 个答案:

答案 0 :(得分:1)

这不是一个错误:它显然是非常有意的。这是对规范的偏差,但它是故意的。

根据警告,听起来他们想要更容易诊断过度发布方案,并且捕获当时正在解除分配的对象可能只是该主要目标的副作用。

他们也可能会考虑,如果你试图在解除分配的同时弱化self,并且你没有检查nil弱点(很常见 - 很多块码反复调用通过一个可以随时nil的弱点!),你正在努力调试bug。

所有这一切,我希望看到运行时改变背后的注释。