循环引用问题 -- dealloc方法不执行

dealloc不执行

如果一个类在释放过后,dealloc方法没有执行,那么就代表着这个类还被其他对象所引用,引用计数不为0,这样就造成了内存泄露

昨天其他业务线开发告知他所依赖的我这边的父类VC的-dealloc 方法不执行,叫我跟一下

于是我很快的想到-dealloc没执行,肯定是循环引用内存泄露之类的问题,于是打开instrument,复现着触发步骤,一个红点,两个红点;嘿,就是你了,结果查找call trees过后就蒙蔽了,报错是jsonmodel的实例方法有问题,难道是某个子类化的JsonModel对象引用了这个VC? 但是这个类有接近两千行,我怎么看?

于是小组大神出场,其在使用了一番instrument过后,发现确实这个VC在释放过后引用计数不为0,但是从各个内存的使用情况啊,调用堆栈啊并看不出错误是出现在哪里(他说instrument改版后不太会用了),在得知我的业务需求过后,于是叫我去用最笨的办法去解决-- 把所有改动屏蔽掉,然后逐个取消屏蔽,看内存泄露在哪一个方法里面

于是尝试,定位,尝试,定位

最终找到循环引用的地方:


在block外面是把self指针置为weak了的,但是进入block过后,却是仍然使用的是强self指针去调用的本类方法,这样一来,便造成了经典的循环引用的问题:

self ---> block  block ---> self

于是VC里面就没办法释放掉,这就是造成VC的dealloc方法未能执行的原因


对于@weakify,@strongify的解释:

#define weakify(...) \\
    autoreleasepool {} \\
    metamacro_foreach_cxt(rac_weakify_,, __weak, __VA_ARGS__)

#define strongify(...) \\
    try {} @finally {} \\
    _Pragma("clang diagnostic push") \\
    _Pragma("clang diagnostic ignored \\"-Wshadow\\"") \\
    metamacro_foreach(rac_strongify_,, __VA_ARGS__) \\
    _Pragma("clang diagnostic pop")

 
 

他们的作用主要是在block内部管理对self的引用:

 @weakify(self); // 定义了一个__weak的self_weak_变量 
[RACObserve(self, name) subscribeNext:^(NSString *name) { 
    @strongify(self); // 局域定义了一个__strong的self指针指向self_weak 
    self.outputLabel.text = name; 
}];

这两个宏一定成对出现,先weak再strong.可以很好的管理Block内部对self的引用。 当然你如果是一个不爱用黄色宏的盆友的话,你可以用原生代码写出来

    __weak typeof(self) weakSelf = self;
    self.Button.rac_command = [[RACCommand alloc] initWithEnabled:textSig signalBlock:^RACSignal *(NSString * input) {

        __strong typeof(weakSelf) strongSelf = weakSelf;
        return nil;
    }];

总结:

在使用instrument的过程中可能因为某些原因,检测不到具体的某个函数的内存泄露,这个时候就不能依赖instrument了(也可能是本渣不太懂怎么调,欢迎指正),这个时候就只能使用最笨的办法 --- 还原二分法来trick了

posted @ 2016-10-06 22:24  Wayne_Liu  阅读(1386)  评论(0编辑  收藏  举报