将来跳槽用技术

iOS基础-内存管理-dealloc方法解析(2)

2023-03-09  本文已影响0人  萧修

当一个对象的引用计数为0的时候,会向他发送一个 release 消息,而在 release 的实现中,会执行 dealloc 方法。

一、基础调用

1、
- (void)dealloc {
    _objc_rootDealloc(self);
}
2、
void _objc_rootDealloc(id obj)
{
    ASSERT(obj);

    obj->rootDealloc();
}

二、核心:rootDealloc()

1、
inline void objc_object::rootDealloc()
{
    if (isTaggedPointer()) return;  // fixme necessary?

    if (fastpath(isa.nonpointer  &&  //是否优化过isa指针
                 !isa.weakly_referenced  &&  //是否存在弱引用指向
                 !isa.has_assoc  &&  //是否设置过关联对象
                 !isa.has_cxx_dtor  &&  //是否有cpp的析构函数
                 !isa.has_sidetable_rc))//引用计数器是否过大,无法存储isa中
    {
        assert(!sidetable_present());
        free(this);//释放
    } 
    else {
        object_dispose((id)this);
    }
}
2、
id  object_dispose(id obj)
{
    if (!obj) return nil;

    objc_destructInstance(obj);    
    free(obj);

    return nil;
}

三、分情况释放
1、释放关联对象、Cpp析构函数

1、释放关联对象、Cpp析构函数
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.
        if (cxx) object_cxxDestruct(obj);//1、销毁有cpp函数
        if (assoc) _object_remove_assocations(obj);//移除关联对象
        obj->clearDeallocating();
    }

    return obj;
}

2、释放弱引用指向

inline void 
objc_object::clearDeallocating()
{
    if (slowpath(!isa.nonpointer)) {//判断是否优化过isa指针
        // Slow path for raw pointer isa.
        sidetable_clearDeallocating();
    }
    else if (slowpath(isa.weakly_referenced  ||  isa.has_sidetable_rc)) {
        /**
        优化过指针,取出sideTable散列表
        */
        // Slow path for non-pointer isa with weak refs and/or side table data.
        clearDeallocating_slow();
    }

    assert(!sidetable_present());
}
2.1 没有优化过isa指针
void  objc_object::sidetable_clearDeallocating()
{
    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_clear_no_lock(&table.weak_table, (id)this);
        }
        table.refcnts.erase(it);
    }
    table.unlock();
}
2.2 优化过isa
NEVER_INLINE void objc_object::clearDeallocating_slow()
{
    ASSERT(isa.nonpointer  &&  (isa.weakly_referenced || isa.has_sidetable_rc));

    SideTable& table = SideTables()[this];
    table.lock();
    if (isa.weakly_referenced) {
        //释放弱引用指向
        weak_clear_no_lock(&table.weak_table, (id)this);
    }
    if (isa.has_sidetable_rc) {
        //判断引用计数表是否还有数据,执行此方法擦除引用引用计数表的引用计数
        table.refcnts.erase(this);
    }
    table.unlock();
}

弱引用指向如何释放和weak修饰有关
关联对象如何

上一篇下一篇

猜你喜欢

热点阅读