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



在Clang的Objective-C自动引用计数中,我们看到以下内容

对于__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 设置为另一个对象的弱属性,应用程序将根据 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;
}

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

根据警告,听起来他们希望更容易诊断过度释放的情况,而捕获当时正在释放的对象可能只是该主要目标的副作用。

他们可能还会考虑,如果你试图在解除分配的同时削弱self,并且你没有检查nil弱引用(很常见 - 许多块代码反复调用弱引用,随时可能nil!),你正在为难以调试的错误做好准备。

综上所述,我很想看到运行时更改背后的注释。

相关内容

  • 没有找到相关文章

最新更新