轉(zhuǎn)自:http://m.itdecent.cn/p/f6e6b4f21ca2
因?yàn)橛龅揭粋€(gè)比較詭異的野指針問(wèn)題,搞了半天才搞定,在此記錄下解決方法。
1、如何調(diào)試僵尸對(duì)象
經(jīng)過(guò)上面的真機(jī)調(diào)試之后,發(fā)現(xiàn)我們的程序崩在了一個(gè)方法里,并且報(bào)錯(cuò) “Thread 1:EXC_BAD_ACCESS(code=1,address=0x4000)”,這種錯(cuò)誤通常是內(nèi)存管理的問(wèn)題,一般是訪問(wèn)了已經(jīng)釋放的對(duì)象導(dǎo)致的,可以開啟僵尸對(duì)象(Zombie Objects)來(lái)定位問(wèn)題。
第一步:還是打開Xcode 選擇屏幕左上角Xcode-> PReferencese,不過(guò)我們這次是要設(shè)置一下輸出信息,調(diào)試的時(shí)候輸出更多的信息,如下截圖,勾上:

設(shè)置.png
第二步:再對(duì)環(huán)境變量進(jìn)行設(shè)置:菜單Product > Scheme > Edit Scheme
把紅色圈里面的三個(gè)選項(xiàng)都勾上

勾上
開啟該選項(xiàng)后,程序在運(yùn)行時(shí),如果訪問(wèn)了已經(jīng)釋放的對(duì)象,則會(huì)給出較準(zhǔn)確的定位信息,可以幫助確定問(wèn)題所在。
該功能的原理是,在對(duì)象釋放(retainCount為0)時(shí),使用一個(gè)內(nèi)置的Zombie對(duì)象,替代原來(lái)被釋放的對(duì)象。無(wú)論向該對(duì)象發(fā)送什么消息(函數(shù)調(diào)用),都會(huì)觸發(fā)異常,拋出調(diào)試信息。
記得在問(wèn)題被修復(fù)后,關(guān)閉該功能?。?/p>
第三步:設(shè)置好后調(diào)試程序,在輸出界面發(fā)現(xiàn)了-[CFString retain]: message sent to deallocated instance錯(cuò)誤日志
到這里,就已經(jīng)很明顯看出來(lái)是什么原因?qū)е鲁绦虮罎⒌牧?,然后再去分析代碼,靜下心來(lái)肯定能解決問(wèn)題的了。
我這里是因?yàn)橄蛞粋€(gè)空的NSString類型發(fā)送消息導(dǎo)致崩潰的,但是這個(gè)問(wèn)題只在iOS9版本崩潰,iOS10就沒問(wèn)題,這個(gè)還值得深究。
2、例子
為了能夠更加詳細(xì)地說(shuō)明調(diào)試僵尸對(duì)象,并定位到崩潰的原因,下面列出一個(gè)簡(jiǎn)單的例子來(lái)說(shuō)明:
先創(chuàng)建一個(gè) DebugViewController,然后里面創(chuàng)建一個(gè)數(shù)組,然后釋放,在Controller將要出現(xiàn)的時(shí)候,向該數(shù)組發(fā)送一個(gè)消息:
#import "DebugViewController.h"
@interface DebugViewController ()
@end
@implementation DebugViewController
/*定義一個(gè)數(shù)組*/
static NSMutableArray*array;
-(void)viewDidLoad
{
[super viewDidLoad];
array= [[NSMutableArray alloc]initWithCapacity:5];
[array release];//釋放掉該數(shù)組
}
- (void)viewWillAppear:(BOOL)animated{
[array addObject:@"Hello"];//使用釋放掉的數(shù)組
}
@end
在我們意料之中,程序崩潰了,報(bào)錯(cuò)信息如下:

崩潰信息.png
我們用LLDB po我們的數(shù)組array對(duì)象,同樣沒有返回

po數(shù)組對(duì)象
打開“活動(dòng)監(jiān)視器”,在進(jìn)程列表中找到測(cè)試APP對(duì)應(yīng)的進(jìn)程號(hào)PID(Xcode啟用調(diào)試后會(huì)在進(jìn)程列表中找到對(duì)應(yīng)APP的進(jìn)程)

活動(dòng)監(jiān)視器.png
從上面標(biāo)下劃線的地方,我們得到兩個(gè)主要的信息:
APP進(jìn)程ID:21122
崩潰地址:0x60008170cfd0
打開“終端”,輸入以下命令:
sudo malloc_history 21122 0x60008170cfd0
得到錯(cuò)誤日志,這樣就能定位到最后調(diào)用的那行代碼

終端.png
就是我們上面的release釋放掉了array對(duì)象導(dǎo)致的。