DDZombieMonitor

2023-02-28  本文已影响0人  是張張啊

核心代码分析:

自定义Dealloc:

- (void)newDealloc:(__unsafe_unretained id)obj {
    if ([self shouldDetect:[obj class]]) {
        void *p = (__bridge void *)obj;
        size_t memSize = malloc_size(p);
        if (memSize >= [DDZombie zombieInstanceSize]) {//有足够的空间才覆盖
            
            Class origClass = object_getClass(obj);
            
            ///析构对象
            objc_destructInstance(obj);
            
            ///填充0x55能稍微提升一些crash率
            memset(p, 0x55, memSize);
            memset(p, 0x00, [DDZombie zombieInstanceSize]);
            
            ///把我们自己的类的isa复制过去
            Class c = [DDZombie zombieIsa];
            memcpy(obj, &c, sizeof(void*));
            
            DDZombie* zombie = (DDZombie*)p;
            
            zombie.realClass = origClass;
            
            //默认为true,即:默认会记录当前僵尸对象释放时的调用栈
            if (_traceDeallocStack) {
                DDThreadStack *stack = hy_getCurrentStack();
                zombie.threadStack = stack;
                memSize += stack->occupyMemorySize();
            }
            
            //check是否达到内存阈值,达到阈值需要释放一部分内存
            [self freeMemoryIfNeed];
            
            //更新内存占用值:_occupyMemorySize
            __sync_fetch_and_add(&_occupyMemorySize, (int)memSize);
            
            //如果保存僵尸对象的队列满了,先将队头的僵尸对象移除并释放内存,再将当前僵尸对象入队。
            void *item = ds_queue_put_pop_first_item_if_need(_delayFreeQueue, p);
            if (item) {
                [self freeZombieObject:item];
            }
        } else {
            [obj performSelector:@selector(hy_originalDealloc)];
        }
    } else {
        [obj performSelector:@selector(hy_originalDealloc)];
    }
}

流程总结 & 验证:

1、析构对象

2、给指针内容填充上0x55

image

3、把DDZombie的isa复制到obj指针中

image

4、将obj原来的类型赋值给僵尸对象的realClass字段

image
上一篇 下一篇

猜你喜欢

热点阅读