版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。
最近项目中出现了一个奇怪bug,后台反映我在1s内同时发起了100多次请求,直接把后台整奔溃了。经过代码核查发现,我是在发送一个通知后,引发的多次后台请求。但是,经过测试我只post一次通知,所以感觉很奇怪,于是乎在addObserver的地方断点,奇怪的现象出现了,明明只post一次通知,但是却接受到了多次通知,所以只能一种可能:注册通知的时候存在多次重复注册通知。为什么会出现这种情况呢?我明明在deinit中移除了该通知,于是乎在deinit中断点,果不其然deinit没有调用,也就是存在内存泄漏。解决多次调用通知这个bug倒是很简单,只需要在viewWillAppear中注册通知,然后在viewDidDisappear中移除该通知即可,但是内存泄漏的问题还是没有被解决,作为一个完美主义者岂能忍,于是乎开启了寻找内存泄漏之旅。
解决内存泄漏肯定首选Instrument,网上教程很多,就不介绍了。运行成功后,进入到内存泄漏的控制器,果然有反应了,leak部分出现红叉,欣喜若狂之际定位到内存泄漏的地方,本以为大功告成了,谁知道一看代码,发现代码并没有问题,不存在内存泄漏啊,导致我各种懵逼。经过反复的确认,定位的代码确实没有问题。但是,至少也给了我一个大致的范围,也不至于瞎找。经过地毯式的搜索,终于找到了内存泄漏的地方,一个block里面的代码没有使用weak修饰,还有一个delegate没有加weak,修改之后测试,deinit方法终于调用,内存泄漏被修复。最后总结一下使用Instrument的正确姿势:
第一步使用Leak找到内存泄漏的地方,如果直接定位到有问题的代码,直接修复即可;如果定位的代码,经过确认后没有问题,那就它定位的代码附近展开地毯式搜索,很快就能找到问题代码的所在之处(这里可以采用控制变量法来进行测试,就是注释掉一部分代码后push->pop,然后看deinit方法有没有调用,不断地缩小问题代码的范围)在寻找内存泄漏的时候不要瞎找,而是要注意几个容易引起内存泄漏的地方:block、delegate、Timer、控制器之间的相互引用、C语言代码(有些需要手动释放内存)