美文网首页iOS 开发 Objective-C
OC 记一次 dealloc 中的 objc_storeWeak

OC 记一次 dealloc 中的 objc_storeWeak

作者: 望穿秋水小作坊 | 来源:发表于2021-08-12 14:53 被阅读0次

1. bugly 崩溃日志如下

image.png

2. 定位到相应的代码段

- (void)dealloc {
    self.splash.delegate = self;
    self.splash = nil;
}
  • Xcode 报错日志如下
 if (deallocating) {
        _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));
    }

3. 崩溃原因

  • 因为手误,将 self.splash.delegate = nil; 写成了 self.splash.delegate = self;
  • 在 dealloc 的时候,self 会被标记成 deallocating 状态,这时候进行 weak 赋值,就会崩溃。
  • 在weak_register_no_lock方法中
  • runtime 检查引用计数的个数来判断对象是否在 deallocting
  • 如果是在deallocting就会报错

4. weak_register_no_lock代码

id 
weak_register_no_lock(weak_table_t *weak_table, id referent_id, id *referrer_id)
{
    objc_object *referent = (objc_object *)referent_id;
    objc_object **referrer = (objc_object **)referrer_id;

    if (!referent  ||  referent->isTaggedPointer()) return referent_id;

    // ensure that the referenced object is viable
    bool deallocating;
    if (!referent->ISA()->hasCustomRR()) {
        deallocating = referent->rootIsDeallocating();
    }
    else {
        BOOL (*allowsWeakReference)(objc_object *, SEL) = 
            (BOOL(*)(objc_object *, SEL))
            object_getMethodImplementation((id)referent, 
                                           SEL_allowsWeakReference);
        if ((IMP)allowsWeakReference == _objc_msgForward) {
            return nil;
        }
        deallocating =
            ! (*allowsWeakReference)(referent, SEL_allowsWeakReference);
    }

    if (deallocating) {
        _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));
    }

    // now remember it and where it is being stored
    weak_entry_t *entry;
    if ((entry = weak_entry_for_referent(weak_table, referent))) {
        append_referrer(entry, referrer);
    } 
    else {
        weak_entry_t new_entry;
        new_entry.referent = referent;
        new_entry.out_of_line = 0;
        new_entry.inline_referrers[0] = referrer;
        for (size_t i = 1; i < WEAK_INLINE_COUNT; i++) {
            new_entry.inline_referrers[i] = nil;
        }

        weak_grow_maybe(weak_table);
        weak_entry_insert(weak_table, &new_entry);
    }

    // Do not set *referrer. objc_storeWeak() requires that the 
    // value not change.

    return referent_id;
}

相关文章

网友评论

    本文标题:OC 记一次 dealloc 中的 objc_storeWeak

    本文链接:https://www.haomeiwen.com/subject/uaslbltx.html