__weak problems

1. Some OC objects cannot be decorated with "__weak", because some classes override the retain and release methods themselves and do not support __weak, such as the NSPort class and its subclasses.

2. Cannot use " " in dealloc , otherwise the program will crash.__weak __typeof(self)weak_self = self;

- (void)dealloc
{
    __weak __typeof(self)weak_self = self;
    NSLog(@"%@", weak_self);
}

When the dealloc is executed, the program crashes.
The crash information is as follows:

objc[4572]: Cannot form weak reference to instance (0x160f6f890) of class MFChatRoomBoardController. It is possible that this object was over-released, or is in the process of deallocation.
(lldb)
error: empty command
(lldb) bt
* thread #1: tid = 0x35914d, 0x0000000182307aac libobjc.A.dylib`_objc_trap(), queue = 'com.apple.main-thread', stop reason = EXC_BREAKPOINT (code=1, subcode=0x182307aac)
  * frame #0: 0x0000000182307aac libobjc.A.dylib`_objc_trap()
    frame #1: 0x0000000182307b24 libobjc.A.dylib`_objc_fatal(char const*, ...) + 88
    frame #2: 0x0000000182319890 libobjc.A.dylib`weak_register_no_lock + 316
    frame #3: 0x0000000182320688 libobjc.A.dylib`objc_initWeak + 224
    frame #4: 0x000000010022bf8c MakeFriends`-[MFChatRoomBoardController dealloc](self=0x0000000160f6f890, _cmd="dealloc") + 36 at MFChatRoomBoardController.m:31


Among them, you can clearly see such a description in the console:

objc[4572]: Cannot form weak reference to instance (0x160f6f890) of class MFChatRoomBoardController. It is possible that this object was over-released, or is in the process of deallocation.

Indicates that it is not allowed to take weak self during dealloc.

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

It can be seen that the runtime determines whether the object is deallocating by checking the number of reference counts, and then passes

    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));
    }
This code crashes the program.

Look at the function _objc_fatal again

void _objc_fatal(const char *fmt, ...)
{
    va_list ap;
    char *buf1;
    char *buf2;

    va_start(ap,fmt);
    vasprintf(&buf1, fmt, ap);
    va_end(ap);

    asprintf(&buf2, "objc[%d]: %s\n", getpid(), buf1);
    _objc_syslog(buf2);
    _objc_crashlog(buf2);

    _objc_trap();
}
You can see that this function actually outputs a piece of information on the console, and then calls _bojc_trap() to cause a crash. And the last function call just happens to be on our previous crash stack.

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325976737&siteId=291194637