ARC中dealloc过程以及.cxx_destruct的探究
ARC文档中对dealloc过程的解释
A class may provide a method definition for an instance method named dealloc. This method will be called after the final release of the object but before it is deallocated or any of its instance variables are destroyed. The superclass’s implementation of dealloc will be called automatically when the method returns.
大概意思是,dealloc方法在最后一次release后,在实例变量被销毁之前,调用;父类的dealloc方法将在子类dealloc返回后自动调用;
The instance variables for an ARC-compiled class will be destroyed at some point after control enters the dealloc method for the root class of the class. The ordering of the destruction of instance variables is unspecified, both within a single class and between subclasses and superclasses.
大概意思是,ARC下的实例变量在调用根类的dealloc方法后被销毁,实例变量销毁的顺序是不固定的,无论在子类还是父类;
所以,ARC下不主动调[super dealloc]是因为编译器自动调用了;
1.NSObject的析构过程
通过查看apple源码,可以看出NSObject调用dealloc实际上是调用了_objc_rootDealloc(源码在NSObject.mm中)
- (void)dealloc {
_objc_rootDealloc(self);
}
_objc_rootDealloc(id obj)
{
ASSERT(obj);
obj->rootDealloc();
}
_objc_rootDealloc接着调用object_dispose(源码在objc-object.h)
objc_object::rootDealloc()
{
if (isTaggedPointer()) return;
object_dispose((id)this);
}
object_dispose最后调用objc_destructInstance(源码在objc-runtime-new.mm)
object_dispose(id obj)
{
if (!obj) return nil;
objc_destructInstance(obj);
free(obj);
return nil;
}
可以看出objc_destructInstance具体做了三件事:
(1)执行object_cxxDestruct(具体做什么下面解释)
(2)执行_object_remove_assocations,删除关联对象的引用
(3)执行clearDeallocating,清空引用计数表并清除弱引用表,将所有的weak引用指为nil。
2.object_cxxDestruct
继续查找object_cxxDestruct,可以看到最后调用了object_cxxDestructFromClass(源码objc-class.mm中)
/***********************************************************************
* object_cxxDestruct.
* Call C++ destructors on obj, if any.
* Uses methodListLock and cacheUpdateLock. The caller must hold neither.
**********************************************************************/
void object_cxxDestruct(id obj)
{
if (!obj) return;
if (obj->isTaggedPointer()) return;
object_cxxDestructFromClass(obj, obj->ISA());
}
/***********************************************************************
* object_cxxDestructFromClass.
* Call C++ destructors on obj, starting with cls's
* dtor method (if any) followed by superclasses' dtors (if any),
* stopping at cls's dtor (if any).
* Uses methodListLock and cacheUpdateLock. The caller must hold neither.
**********************************************************************/
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);
}
}
}
代码不难理解,沿着继承链逐层向上查找SEL_cxx_destruct这个函数,找到函数实现并执行,现在就找到我们之前的.cxx_destruct方法。
初始化Test类,在如图断点处,输入lldb指令:
watchpoint set variable test->_address
将address的变量加入watchpoint
(lldb) watchpoint set variable test->_address
Watchpoint created: Watchpoint 1: addr = 0x10054b038 size = 8 state = enabled type = w
watchpoint spec = 'test->_address'
new value: 0x00000001000040a8
Watchpoint 1 hit:
old value: 0x00000001000040a8
new value: 0x0000000000000000
可以看出_address从 0x00000001000040a8 变成了 0x0000000000000000,也就是nil,看下调用栈,果然跟到了.cxx_destruct方法,而且是在objc_storeStrong的过程中释放。
总结: ARC下对象的成员变量于编译器插入的.cxx_desctruct方法中释放; ARC下[super dealloc]方法由编译器自动插入; cxx_destruct内部实现需进一步探索;