オブジェクトOCの破壊過程を解析することにより、ランタイムobjc4-779.1ソースランタイム

オブジェクトOCの破壊過程を解析することにより、ランタイムobjc4-779.1ソースランタイム

ステップ1 NSObject.mmライン2340

// Replaced by NSZombies
- (void)dealloc {
	// Setp2
    _objc_rootDealloc(self);
}

ステップ2 NSObject.mmライン1814

void
_objc_rootDealloc(id obj)
{
// 判断对象是否真是存在,不存在则结束
    ASSERT(obj);
	// Step3
    obj->rootDealloc();
}

ステップ3にObjC-object.hライン433

inline void
objc_object::rootDealloc()
{
	// 如果是tagged pointer 则结束, 因为它不按照对象的内存管理来,仅仅是一个指针,指针中含有对象相关的信息,包含它的值, 如果不知道什么个tagged pointer 可以看之前的博文 https://blog.csdn.net/wxs0124/article/details/82712478
    if (isTaggedPointer()) return;  // fixme necessary?

	// 如果对象已成创建isa_t(初始化),没有被weak修饰,没有关联其他对象,没有实现C++析构方法,没有因引用计数过多而存储在sidetable中
    if (fastpath(isa.nonpointer  &&  
                 !isa.weakly_referenced  &&  
                 !isa.has_assoc  &&  
                 !isa.has_cxx_dtor  &&  
                 !isa.has_sidetable_rc))
    {
        //判定本对象不存在于sidetable中
        assert(!sidetable_present());
        //释放
        free(this);
    } 
    else {
    	// 此步需要进一步解析
    	// Step4
        object_dispose((id)this);
    }
}

ステップ4 objc-runtime-new.mmライン7564

id 
object_dispose(id obj)
{
    if (!obj) return nil;
	// 处理c++析构过程,移除对象关联,clear
	// Step5
    objc_destructInstance(obj);    
    free(obj);

    return nil;
}

ステップ5 objc-runtime-new.mmライン7542

void *objc_destructInstance(id obj) 
{
    if (obj) {
        // Read all of the flags at once for performance.
        // 是否有c++/OC析构函数
        bool cxx = obj->hasCxxDtor();
        // 是否有其他关联
        bool assoc = obj->hasAssociatedObjects();

        // This order is important.
        // 进行析构,详见 Step6
        if (cxx) object_cxxDestruct(obj);
        // 移除所有相关的关联对象,详见 Step7
        if (assoc) _object_remove_assocations(obj);
        // 清理内存空间 详见Step8
        obj->clearDeallocating();
    }

    return obj;
}

ステップ6 objc-class.mmライン463

void object_cxxDestruct(id obj)
{
    if (!obj) return;
    if (obj->isTaggedPointer()) return;
    // Step6.1
    object_cxxDestructFromClass(obj, obj->ISA());
}

6.1 objc-class.mmライン437

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) {
    
    	// 如果没有实现c++/OC析构方法,则结束
        if (!cls->hasCxxDtor()) return; 
        
        // 在本类中找到析构方法并且记载到缓存中 , 方法实现在objc-class-old.mm line 578 此处不展开
        dtor = (void(*)(id))
            lookupMethodInClassAndLoadCache(cls, SEL_cxx_destruct);
        
        // 因为lookupMethodInClassAndLoadCache只会在本类中寻找方法(不会去父类),找不到则会返回objc_msgForward, _objc_msgForward_impcache是编译器的消息转发标记,代表此方法要走消息转发,如果析构方法在本类中被找到了,则此一定为true,进入代码块,执行代码.
        if (dtor != (void(*)(id))_objc_msgForward_impcache) {
            if (PrintCxxCtors) {
                _objc_inform("CXX: calling C++ destructors for class %s", 
                             cls->nameForLogging());
            }
            (*dtor)(obj);
        }
    }
}

ステップ7 objc-references.mmライン217

関連テーブルから関連するオブジェクトを削除します

void
_object_remove_assocations(id object)
{
    ObjectAssociationMap refs{};

    {
        AssociationsManager manager;
        AssociationsHashMap &associations(manager.get());
        // 便利查找到和object相关的map并从其中移除记录
        AssociationsHashMap::iterator i = associations.find((objc_object *)object);
        if (i != associations.end()) {
            refs.swap(i->second);
            associations.erase(i);
        }
    }

    // release everything (outside of the lock).
    for (auto &i: refs) {
        i.second.releaseHeldValue();
    }
}

ここでのコードは、現在関連付けられた関連オブジェクトを見つけるassociationHashMap本当に、そして打た
協会が独立し、重要なポイントである。関連テーブルストレージフォーマット、アクセスモードのオブジェクト、プロセス、メモリ管理を巻き込む、我々はブログに戻ってきますで議論を詳細に説明。ここで着手していません

ステップ8にObjC-object.hライン417


inline void 
objc_object::clearDeallocating()
{
	// 如果是只有isa指针,没有优化成isa_t
    if (slowpath(!isa.nonpointer)) {
        // Slow path for raw pointer isa.
        sidetable_clearDeallocating();
    }
    else if (slowpath(isa.weakly_referenced  ||  isa.has_sidetable_rc)) {
    // 如果没有被弱引用,或者 在sidetable中查不到(意味着引用计数没有太大,在isa_t中存储)
        // Slow path for non-pointer isa with weak refs and/or side table data.
        clearDeallocating_slow();
    }

    assert(!sidetable_present());
}

Step8.1 NSObject.mmライン1552

空に(任意のアプリケーションオブジェクトの保存カウント情報のISAを格納するための、あまりにも多くの参照カウントによる)sidetableデータ

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();
}

Step8.2 NSObject.mmライン1212

// Slow path of clearDeallocating() 
// for objects with nonpointer isa
// that were ever weakly referenced 
// or whose retain count ever overflowed to the side table.
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();
}

要約すると:

  • オブジェクトのコアメソッドが解除されますvoid *objc_destructInstance(id obj)
  • コアは、継承チェーン呼び出しC ++ / OC .2デストラクタに沿って、1を処理し、削除は、ポインタに関連付けられたオブジェクト、記録.weak nil.3に設定変更に弱い対象レコードの除去とその参照weak_tableを更新していますデータを数えます。
  • 知識はまだ一般的AssociationsHashMap、弱い、参照カウントである、同じまま。私たちは一つ一つを破ります
发布了139 篇原创文章 · 获赞 35 · 访问量 41万+

おすすめ

転載: blog.csdn.net/wxs0124/article/details/104537421