为什么将要进行重新分配的对象设置为弱属性会导致崩溃 [英] Why setting object that is undergoing deallocation to weak property results in crash

查看:152
本文介绍了为什么将要进行重新分配的对象设置为弱属性会导致崩溃的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

In Clang's Objective-C Automatic Reference Counting we see the following

对于__weak对象,除非新指针是当前正在释放的对象,否则将更新左值以指向新指针,在这种情况下,左值将更新为空指针.对于其他分配给对象,从对象读取以及最终指向新指针的对象,这必须原子执行.

For __weak objects, the lvalue is updated to point to the new pointee, unless the new pointee is an object currently undergoing deallocation, in which case the lvalue is updated to a null pointer. This must execute atomically with respect to other assignments to the object, to reads from the object, and to the final release of the new pointee.

objc-weak.mm weak_register_no_lock()中看到以下代码块:

In objc-weak.mm wee see the following chunk of code in 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值.

I set a breakpoint in my UIViewController subclass dealloc method and tried invoking [self allowsWeakReference] in lldb which resulted in NO value.

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

If we try to set self to weak property of another object the app will crash in accordance with the objc-weak.mm code.

问题是–为什么会发生这种情况? lang的规格是否错误?这是objc实现中的错误吗?

The question is – why does this happen? Is the clang's specification wrong? Is is this a bug in objc implementation?

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

Here is a simple piece of code that will reproduce the crash:

//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;
}

推荐答案

这不是bug:很明显是故意的.这是对规范的偏离,但这是有意的.

It's not a bug: it's obviously very intentional. It is a deviation from the spec, but it's an intentional one.

根据警告,听起来他们想简化诊断过度释放的情况,并且捕获当时被释放的对象可能只是该主要目标的副作用.

Based on the warning, it sounds like they wanted to make it easier to diagnose over-release scenarios, and catching objects that are being deallocated at the time might just be a side effect of that main goal.

他们还可能认为,如果您试图在释放时仍然削弱self,并且没有检查nil弱引用(很常见-许多块代码通过一个弱引用反复调用可能会随时出现nil!),您正在设置自己以调试错误.

They might also consider that, if you're trying to weakify self while being deallocated anyway, and you're not checking for a nil weakref (quite common - lots of block code repeatedly calls through a weakref that could go nil at any time!), you're setting yourself up for hard to debug bugs.

所有这些,我很乐意看到运行时更改背后的注释.

All that said, I'd love to see the notes behind that runtime change.

这篇关于为什么将要进行重新分配的对象设置为弱属性会导致崩溃的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆