weak_register_no_lock crash 崩溃的解

作者: Pandakingli | 来源:发表于2017-02-14 16:49 被阅读241次

    崩溃的栈为:

    Thread 0 Crashed:
    0 objc_crashlogPKc 
    1 __objc_fatal 
    2 _weak_register_no_lock 
    3 _objc_storeWeak
    

    一般在dealloc中取weak self会引起这个现象

    - (void)dealloc
    {
        __weak __typeof(self)wself = self;
        NSLog(@"%@", wself);//或者其他的调用
    }
    

    原因:
    在weak_register_no_lock方法中
    runtime 检查引用计数的个数来判断对象是否在 deallocting
    如果是在deallocting就会报错

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

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

    相关文章

      网友评论

        本文标题:weak_register_no_lock crash 崩溃的解

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