iOS基础---OC runtime篇二之对象dealloc后发生了什么?

对象的dealloc调用后发生了什么?

本文对应的源码见:https://github.com/huangturen/objc-runtime

第一、最简单的类(没有任何成员变量,没有任何引用的类)其dealloc的过程为何?

我们创建一个类TestObject1,使其继承自NSObject,在main函数中创建一个TestObject1的临时变量,观察其dealloc过程:

static void testDeallocSimple(){
    TestObject1 *obj1 = [TestObject1 new];
    NSLog(@"%@",obj1);
}

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        testDeallocSimple();
    }
    return 0;
}

当testDeallocSimple()执行结束时,obj1对象需要析构,在NSObject.mm的dealloc方法中,我们断点,会发现调用顺序为:

显然,调用顺序为:先调用当前类的dealloc,然后调用NSObject类的dealloc。这里我们可以推定,多次继承的情况下其dealloc调用顺序应该为:先子类然后父类的顺序,最后到了NSObject根类。这个结论也不难验证,再上面示例的基础上,我们再多继承一次后的调用情况如图所示:

所以,一个类的dealloc执行后,其会依次调用父类的dealloc方法,直到NSObject的dealloc为止。

那么NSObject的dealloc执行时发生了什么?

其实际的调用链为:

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

void 
_objc_rootDealloc(id obj)
{
    assert(obj);

    obj->rootDealloc();
}

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

    if (fastpath(isa.nonpointer  &&  
                 !isa.weakly_referenced  &&  
                 !isa.has_assoc  &&  
                 !isa.has_cxx_dtor  &&  
                 !isa.has_sidetable_rc))
    {
        assert(!sidetable_present());
        free(this);
    } 
    else {
        object_dispose((id)this);
    }
}

上述TestObject执行了free(this)这个分支,即dealloc后,直接释放了内存,然后结束。

第二、当类有一个成员变量时,其dealloc过程为何?

我们定义一个测试类TestObjectWithProperty:

@interface TestObjectWithProperty : NSObject

@property(nonatomic, strong)NSMutableArray *array;

@end

然后采用上述同样的方式测试,来观察整个dealloc流程。这里我们发现objc_object::rootDealloc()方法中执行了object_dispose((id)this);通过lld调试,发现TestObjectWithProperty的isa结构体成员变量值如下:

(lldb) po isa.nonpointer
1

(lldb) po isa.weakly_referenced
<nil>

(lldb) po isa.has_assoc
<nil>

(lldb) po isa.has_cxx_dtor
1

(lldb) po isa.has_sidetable_rc
<nil>

所以,显然当前类的属性has_cxx_dtor为true;这里has_cxx_dtor意思是当前类有方法[TestObjectWithProperty .cxx_destruct],此方法是编译期自动为类添加,具体的添加规则,我们可以在类的初始化流程中去分析。所以,以上逻辑可以看出,OC对象销毁有两种调用路径: 我们可以称之为快速销毁一般销毁.为了解释方便理解这两种销毁路径,我们有必要解释一下isa的成员变量的意义,参考http://www.sealiesoftware.com/blog/archive/2013/09/24/objc_explain_Non-pointer_isa.html.

isa结构体成员变量意义
名称意义长度
nonpointer

0 is raw isa, 1 is non-pointer isa

0表示指针(指针只用来描述地址),1表示优化后的指针(除了描述地址以外还做了一些其他的事儿)

1
has_assoc

Object has or once had an associated reference. Object with no associated references can deallocate faster.

有或曾经有过关联对象

1
has_cxx_dtor

Object has a C++ or ARC destructor. Objects with no destructor can deallocate faster.

有C++ 或 ARC 析构器

1
shiftcls

Class pointer's non-zero bits.

类指针的非空字节

44
magic

Equals 0xd2. Used by the debugger to distinguish real objects from uninitialized junk.

有固定的值,debugger用来区分未初始化的变量

6
weakly_referenced

Object is or once was pointed to by an ARC weak variable. Objects not weakly referenced can deallocate faster.

被或曾经被弱引用过

1
deallocating

Object is currently deallocating.

正在dealloc

1
has_sidetable_rc

Object's retain count is too large to store inline.

对象的保留计数过大

1
extra_rc

Object's retain count above 1. (For example, if extra_rc is 5 then the object's real retain count is 6.)

此值+1则为对象的引用计数

8

从上述解释不难看出,对象快速销毁发生在:指针被优化过,没有被弱引用,没有关联对象,没有C++或ARC析构器,以及引用计数可以内连储存时------本质上是当前对象的所有信息都存在在这一个指针内时.

第三、一般销毁object_dispose的具体操作是什么?

id 
object_dispose(id obj)
{
    if (!obj) return nil;

    objc_destructInstance(obj);    
    free(obj);

    return 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.
        if (cxx) object_cxxDestruct(obj);
        if (assoc) _object_remove_assocations(obj);
        obj->clearDeallocating();
    }

    return obj;
}

从object_dispose的实现来看,其首先执行objc_destructInstance方法,然后释放内存。而objc_destructInstance具体的工作包括三部分:

1、如果当前实例有.cxx_Destruct方法,则执行之;

2、如果当前实例有关联对象,则移除之;

3、执行clearDeallocating,其内部所做的工作为从weak列表中移除(如果被弱引用)以及销毁引用计数的存储指针(如果引用计数很大不能内联存储),这里的weak列表和引用计数都保存在一个叫SideTable的全局结构体中,此结构体在runtime运行期内不会被析构;

 

完!

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值