【问题标题】:Why setting object that is undergoing deallocation to weak property results in crash为什么将正在进行释放的对象设置为弱属性会导致崩溃
【发布时间】:2016-06-29 17:12:39
【问题描述】:

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

【问题讨论】:

  • 那么你想知道什么;为什么您的应用程序崩溃或为什么设置一个指向释放对象的弱指针会导致 null?另外你为什么认为这两件事是相关的?
  • 我稍微编辑了我的问题以使用最新的 objc-weak.mm 源。
  • 但是你没有回答我的问题。
  • 对不起,我按回车很快。我看到两个相互矛盾的陈述。第一个是设置一个指向释放对象的弱指针应该导致 nil。但是在 objc-weak 的源代码中我们看到它反而会导致崩溃。我假设在释放期间将self 存储到弱属性是完全合法的,但现在我发现它不是。不是bug吗?
  • 什么设置crashIfDeallocating

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


【解决方案1】:

这不是错误:这显然是故意的。这是与规范的偏差,但这是故意的。

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

他们也可能会考虑,如果你试图弱化 self 同时被释放,并且你没有检查 nilweakref (很常见 - 很多块代码通过一个 weakref 反复调用随时可以去nil!),您正在为难以调试的错误做好准备。

说了这么多,我很想看看运行时更改背后的注释。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-08
    • 2011-01-23
    • 1970-01-01
    • 2021-06-28
    • 1970-01-01
    相关资源
    最近更新 更多