iOS Objective-C底层 part4:die

生对死,allocdealloc

alloc经历了一些周折才调用calloc,开辟内存空间.
dealloc也一样经历了一些周折才调用free,释放了内存空间.

1. dealloc流程

dealloc.png

调用栈如上图.其实可以将分支合并:isa.nonpointer&&!isa.weakly_referenced&&!isa.has_assoc&& !isa.has_cxx_dtor&&!isa.has_sidetable_rc

  • 条件1:isa.nonpointer

是否是支持nonpointerisa,不支持直接free;(不支持nonpointerisa,下面的条件都不必看)

  • 条件2:isa.has_cxx_dtor

是否有C++的析构函数,为真,则要调用析构函数;

  • 条件3:isa.has_assoc

是否有关联属性,为真,则要解除关联属性;

  • 条件4:isa.weakly_referenced

是否有weak指针指向该对象,为真,则要将所有指向该对象的weak指针全部置为nil;

  • 条件5:isa.has_sidetable_rc

是否开启了Sidetable来储存该对象的retainCount,为真,则要将该对象对应的Sidetable内储存的retainCount清除.

5个条件全部走完,再调用free,收工.

2. 哪里不对?

问题1:ARC环境下不用书写对象对自己实例变量引用解除的代码,为什么流程中不见对自己实例变量解除引用的代码?

答:一个方法,一个标记.

@interface PGCustomClass : NSObject
@property(nonatomic,copy)NSString * name;
@end

生成PGCustomClass对象时,看initInstanceIsa的参数:

initInstanceIsa_1.png

@interface PGCustomClass2 : NSObject

@end

生成PGCustomClass对象时,看initInstanceIsa的参数:

initInstanceIsa_2.png

  • 一个标记

很明显,带实例变量的类的obj->isa.has_cxx_dtor==1;
很明显,不带实例变量的类的obj->isa.has_cxx_dtor==0;
实例变量(是不是属性格式无所谓).
obj->isa.has_cxx_dtor,追溯根源还是来自类的bits->flags.

  • 一个方法

PGCustomClassPGCustomClass2内加入以下代码,打印方法列表:

- (void)logMethods
{
    unsigned int count;
    Method *methods = class_copyMethodList([self class], &count);
    for (int i = 0; i < count; i++)
    {
        Method method = methods[i];
        SEL selector = method_getName(method);
        NSString * name = NSStringFromSelector(selector);
        NSLog(@"方法名:%@",name);
    }
}

PGCustomClass:

logMethods
.cxx_destruct

PGCustomClass2:

logMethods

很明显,带实例变量的类多出一个.cxx_destruct方法,是编译器加的.

一个标记+一个方法==>如下效果:

isa.has_cxx_dtor==1;
└─object_cxxDestructFromClass
  └─.cxx_destruct

isa.has_cxx_dtor==1;才会调用object_cxxDestructFromClass,进而调用.cxx_destruct.

.cxx_destruct方法内就是做了对象对自己实例变量的引用解除

static void object_cxxDestructFromClass(id obj, Class cls)
{
    void (*dtor)(id);

    // Call cls's dtor first, then superclasses's dtors.

    for ( ; cls; cls = cls->superclass) {
        if (!cls->hasCxxDtor()) return; 
        dtor = (void(*)(id))
            lookupMethodInClassAndLoadCache(cls, SEL_cxx_destruct);
        if (dtor != (void(*)(id))_objc_msgForward_impcache) {
            if (PrintCxxCtors) {
                _objc_inform("CXX: calling C++ destructors for class %s", 
                             cls->nameForLogging());
            }
            (*dtor)(obj);
        }
    }
}

isa.has_cxx_dtor除了标记当前类是否有C++的析构函数外,被赋予了其他公用:标记对象是否有实例变量;

为什么有实例变量的类才加标记方法呢?
原因也很简单,因为只有这样的类生成的对象才会实例变量,对象有实例变量才需要解除引用.

问题2:ARC环境下-dealloc内不能书写[super dealloc],为什么流程中也不见调用父类的dealloc?
由上面的逻辑推算,[super dealloc]也是编译器加的.详情请戳


文章参考:
objc源码
ARC下dealloc过程及.cxx_destruct的探究

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 转至元数据结尾创建: 董潇伟,最新修改于: 十二月 23, 2016 转至元数据起始第一章:isa和Class一....
    40c0490e5268阅读 2,163评论 0 9
  • 29.理解引用计数 Objective-C语言使用引用计数来管理内存,也就是说,每个对象都有个可以递增或递减的计数...
    Code_Ninja阅读 1,797评论 1 3
  • 前言 在面向对象编程中,我们每天都在创建对象,用对象描述着整个世界,然而对象是如何从孕育到销毁的呢? 目录 1.孕...
    一缕殇流化隐半边冰霜阅读 12,285评论 75 161
  • 来源:http://blog.sunnyxx.com/2014/04/02/objc_dig_arc_deallo...
    看之学之阅读 964评论 0 5
  • 今天折腾了好久,情绪才基本恢复到原状。人到崩溃时,我听到了自己的哭声,却是干哭,没有眼泪。找了三个人倾诉,吃了一顿...
    天堂鸟_fd83阅读 118评论 0 0

友情链接更多精彩内容