iOS try-catch会引起memory leak

最近碰到了一个很棘手的问题----内存泄露。

话说某天早晨,在需求完成时检查各种场景下WebView的使用是否正常,特别是内存释放是否正常时,发现了一个问题,在某个内嵌WebView的场景下WebView实例始终不释放。着实吓了我一跳,然后检查了一下前几个版本的代码,发现这种场景下一直都没有释放,可见问题久亦。在评估了对线上版本的影响后,我就开始了漫长的内存泄露定位之旅。

1、检查了持有WebView的对象是否正常释放----对方的对象是dealloc的!

2、代码层面寻找block环引用,捋了所有的block,没有发现异常!

3、使用Xcode工具View Memory Graph Hierarchy:


是不是很干净?没有人对WebView形成强引用。上面出现的WKWebView的信息是因为我封装的WebView实例是WKWebView的UIDelegate。这是个弱引用。

从上图倒了祖宗十八代也没有查到有用的信息。

4、是不是有很深的环呢?一般情况下xcode这些工具在检查环的时候应该有查找的上限阈值,会不会漏了呢。这个时候想到了Facebook的查环神器FBRetainCycleDetector。把环的深度放了很大,但是仍然一无所获。

5、开始最蠢的办法,开始逐行注释代码,哪行代码注掉内存释放正确就是哪行的问题。结果这个最蠢的方法最有效,不到半个小时,凶手抓住了。先看出问题的代码

    if (![self.webView.realWebView isKindOfClass:[UIWebView class]]) {

        @try {

            [self.webView.scrollView setValue:xxxxxx forKey:yyyyyy;

        }

        @catch (NSException *exception) {

            self.webView.scrollView.zzzzzz = pppppp;

        }

    } else {

        do something in else

    }

我们自以为是的使用了try-catch机制来处理OC的问题,但这个机制在ARC下默认是memory-leak的。正如苹果的解释如下:


Rationale

The standard Cocoa convention is that exceptions signal programmer error and are not intended to be recovered from. Making code exceptions-safe by default would impose severe runtime and code size penalties on code that typically does not actually care about exceptions safety. Therefore, ARC-generated code leaks by default on exceptions, which is just fine if the process is going to be immediately terminated anyway. Programs which do care about recovering from exceptions should enable the option.


唉,就这么个问题费了这么大的劲儿才找到。Mark一下:OC中不要轻易使用try-catch!!!!

续:有同事告诉我这个问题在

《Effective OC 2.0:编写高质量iOS与OS X代码的52个有效方法》

中有讨论,这可是我的OC的入门书籍,结果忘了。可见读书不精,遗憾,后面赶紧要捡起来了!

猜你喜欢

转载自blog.csdn.net/u012413955/article/details/79816579