objc_dealloc流程及处理逻辑

源码分析

dealloc

  • dealloc方法中调用了_objc_rootDealloc方法
// Replaced by NSZombies

- (**void**)dealloc {
  _objc_rootDealloc(**self**);
}

_objc_rootDealloc

  • _objc_rootDealloc 方法中调用了rootDealloc方法
void _objc_rootDealloc(id obj)
{
    ASSERT(obj);
    obj->rootDealloc();
}

rootDealloc

  • rootDealloc方法中处理见源码注释
inline void
objc_object::rootDealloc()
{
    //如果是TaggedPointer 直接返回
    if (isTaggedPointer()) return;  

    if (fastpath(isa.nonpointer                     &&  //如果是nonpointer
                 !isa.weakly_referenced             &&  //如果没有被弱引用
                 !isa.has_assoc                     &&  //如果没有关联对象
#if ISA_HAS_CXX_DTOR_BIT
                 !isa.has_cxx_dtor                  &&  //如果没有C++的析构函数
#else
                 !isa.getClass(false)->hasCxxDtor() &&
#endif
                 !isa.has_sidetable_rc))  //如果没有sidetable_rc
    {
        assert(!sidetable_present());
      //直接free
        free(this);
    } 
    else {
        object_dispose((id)this);
    }
}

objc_dispose

  • objc_dispose中调用了 objc_destructInstance方法
id object_dispose(id obj)
{
    if (!obj) return nil;

    objc_destructInstance(obj);    
    free(obj);

    return nil;
}

objc_destructInstance

/***********************************************************************
* objc_destructInstance
* Destroys an instance without freeing memory. 
* Calls C++ destructors.
* Calls ARC ivar cleanup.
* Removes associative references.
* Returns `obj`. Does nothing if `obj` is nil.
**********************************************************************/
void *objc_destructInstance(id obj) 
{
    if (obj) {
        // Read all of the flags at once for performance.
        bool cxx = obj->hasCxxDtor();
        bool assoc = obj->hasAssociatedObjects();

        // This order is important.
        //如果有C++的析构函数,执行C++析构函数
        if (cxx) object_cxxDestruct(obj);
        //如果有关联对象,移除关联对象
        if (assoc) _object_remove_assocations(obj, /*deallocating*/true);
        obj->clearDeallocating();
    }

    return obj;
}   

sidetable_clearDeallocating

void 
objc_object::sidetable_clearDeallocating()
{
    //从Sidetables对象指针找到对应的SideTable。
    SideTable& table = SideTables()[this];

    // clear any weak table items
    // clear extra retain count and deallocating bit
    // (fixme warn or abort if extra retain count == 0 ?)
    table.lock();
    RefcountMap::iterator it = table.refcnts.find(this);
    if (it != table.refcnts.end()) {
        if (it->second & SIDE_TABLE_WEAKLY_REFERENCED) {
            //清空所有的weak对象
            weak_clear_no_lock(&table.weak_table, (id)this);
        }
        //从引用计数表擦除
        table.refcnts.erase(it);
    }
    table.unlock();
}

weak_clear_no_lock

  • 找到对应的弱引用对象并置位nil
void 
weak_clear_no_lock(weak_table_t *weak_table, id referent_id) 
{
    objc_object *referent = (objc_object *)referent_id;

    weak_entry_t *entry = weak_entry_for_referent(weak_table, referent);
    if (entry == nil) {
        /// XXX shouldn't happen, but does with mismatched CF/objc
        //printf("XXX no entry for clear deallocating %p\n", referent);
        return;
    }

    // zero out references
    weak_referrer_t *referrers;
    size_t count;
    
    if (entry->out_of_line()) {
        referrers = entry->referrers;
        count = TABLE_SIZE(entry);
    } 
    else {
        referrers = entry->inline_referrers;
        count = WEAK_INLINE_COUNT;
    }
    
    for (size_t i = 0; i < count; ++i) {
        objc_object **referrer = referrers[i];
        if (referrer) {
            if (*referrer == referent) {
                *referrer = nil;
            }
            else if (*referrer) {
                _objc_inform("__weak variable at %p holds %p instead of %p. "
                             "This is probably incorrect use of "
                             "objc_storeWeak() and objc_loadWeak(). "
                             "Break on objc_weak_error to debug.\n", 
                             referrer, (void*)*referrer, (void*)referent);
                objc_weak_error();
            }
        }
    }
    
    weak_entry_remove(weak_table, entry);
}

weak_entry_for_referent

static weak_entry_t *
weak_entry_for_referent(weak_table_t *weak_table, objc_object *referent)
{
    ASSERT(referent);

    weak_entry_t *weak_entries = weak_table->weak_entries;

    if (!weak_entries) return nil;
        //拿到当前对象的指针&一个mask得到一个索引
    size_t begin = hash_pointer(referent) & weak_table->mask;
      //拿到索引
    size_t index = begin;
    size_t hash_displacement = 0;
    //遍历哈希表,取得当前对象
    while (weak_table->weak_entries[index].referent != referent) {
        index = (index+1) & weak_table->mask;
        if (index == begin) bad_weak_table(weak_table->weak_entries);
        hash_displacement++;
        if (hash_displacement > weak_table->max_hash_displacement) {
            return nil;
        }
    }
    
    return &weak_table->weak_entries[index];
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容