zoukankan      html  css  js  c++  java
  • __weak存在的问题

    1、有些OC对象不能使用 "__weak" 修饰,因为有些类自己重写了retain和release方法,不支持__weak,例如NSPort类和它的子类。

    2、在dealloc中不能使用 “__weak __typeof(self)weak_self = self;”,否则程序会崩溃。

    - (void)dealloc
    {
        __weak __typeof(self)weak_self = self;
        NSLog(@"%@", weak_self);
    }
    
    当执行到dealloc的时候,程序就crash 掉了。
    崩溃信息如下:
    
    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
    
    
    其中,可以在控制台明确看到这样一段描述:
    
    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.
    
    说明不允许在 dealloc 的时候取 weak self.
    
    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;
    }
    
    可以看出,runtime 是通过检查引用计数的个数来判断对象是否在 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));
        }
    这段代码让程序crash。
    
    再看一下 _objc_fatal 这个函数
    
    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
    ", getpid(), buf1);
        _objc_syslog(buf2);
        _objc_crashlog(buf2);
    
        _objc_trap();
    }
    可以看到这个函数实际会在控制台输出一段信息,然后调用 _bojc_trap() 引起 crash. 而最后一个函数调用刚好也对上我们之前的崩溃堆栈。
  • 相关阅读:
    实用机器学习 跟李沐学AI
    Explicitly drop temp table or let SQL Server handle it
    dotnettransformxdt and FatAntelope
    QQ拼音输入法 禁用模糊音
    (技术八卦)Java VS RoR
    Ruby on rails开发从头来(windows)(七)创建在线购物页面
    Ruby on rails开发从头来(windows)(十三)订单(Order)
    Ruby on rails开发从头来(windows)(十一)订单(Order)
    新员工自缢身亡,华为又站到了风口浪尖
    死亡汽油弹(Napalm Death)乐队的视频和来中国演出的消息
  • 原文地址:https://www.cnblogs.com/Zp3sss/p/9011725.html
Copyright © 2011-2022 走看看