轉自:http://www.reibang.com/p/f6e6b4f21ca2
因為遇到一個比較詭異的野指針問題,搞了半天才搞定嘱丢,在此記錄下解決方法卸耘。
1、如何調試僵尸對象
經(jīng)過上面的真機調試之后伍俘,發(fā)現(xiàn)我們的程序崩在了一個方法里邪锌,并且報錯 “Thread 1:EXC_BAD_ACCESS(code=1,address=0x4000)”,這種錯誤通常是內存管理的問題癌瘾,一般是訪問了已經(jīng)釋放的對象導致的觅丰,可以開啟僵尸對象(Zombie Objects)來定位問題。
第一步:還是打開Xcode 選擇屏幕左上角Xcode-> PReferencese妨退,不過我們這次是要設置一下輸出信息妇萄,調試的時候輸出更多的信息蜕企,如下截圖,勾上:
設置.png
第二步:再對環(huán)境變量進行設置:菜單Product > Scheme > Edit Scheme
把紅色圈里面的三個選項都勾上
勾上
開啟該選項后冠句,程序在運行時轻掩,如果訪問了已經(jīng)釋放的對象,則會給出較準確的定位信息懦底,可以幫助確定問題所在放典。
該功能的原理是,在對象釋放(retainCount為0)時基茵,使用一個內置的Zombie對象,替代原來被釋放的對象壳影。無論向該對象發(fā)送什么消息(函數(shù)調用)拱层,都會觸發(fā)異常,拋出調試信息宴咧。
記得在問題被修復后根灯,關閉該功能!掺栅!
第三步:設置好后調試程序烙肺,在輸出界面發(fā)現(xiàn)了-[CFString retain]: message sent to deallocated instance錯誤日志
到這里,就已經(jīng)很明顯看出來是什么原因導致程序崩潰的了氧卧,然后再去分析代碼桃笙,靜下心來肯定能解決問題的了。
我這里是因為向一個空的NSString類型發(fā)送消息導致崩潰的沙绝,但是這個問題只在iOS9版本崩潰搏明,iOS10就沒問題,這個還值得深究闪檬。
2星著、例子
為了能夠更加詳細地說明調試僵尸對象,并定位到崩潰的原因粗悯,下面列出一個簡單的例子來說明:
先創(chuàng)建一個 DebugViewController虚循,然后里面創(chuàng)建一個數(shù)組,然后釋放样傍,在Controller將要出現(xiàn)的時候横缔,向該數(shù)組發(fā)送一個消息:
#import "DebugViewController.h"
@interface DebugViewController ()
@end
@implementation DebugViewController
/*定義一個數(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
在我們意料之中,程序崩潰了铭乾,報錯信息如下:
崩潰信息.png
我們用LLDB po我們的數(shù)組array對象剪廉,同樣沒有返回
po數(shù)組對象
打開“活動監(jiān)視器”,在進程列表中找到測試APP對應的進程號PID(Xcode啟用調試后會在進程列表中找到對應APP的進程)
活動監(jiān)視器.png
從上面標下劃線的地方炕檩,我們得到兩個主要的信息:
APP進程ID:21122
崩潰地址:0x60008170cfd0
打開“終端”斗蒋,輸入以下命令:
sudo malloc_history 21122 0x60008170cfd0
得到錯誤日志捌斧,這樣就能定位到最后調用的那行代碼
終端.png
就是我們上面的release釋放掉了array對象導致的。