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修饰有关
关联对象如何