天天看點

利用 僵屍環境變量 找出Crash原因( 僵屍斷點 )

     iOS程式Crash,如果由于程式上的的邏輯錯誤或者數組越界,一般都會有錯誤日志會輸出錯誤的原因,已經跟蹤堆棧錯誤資訊。但是 有的時候,就會沒有任何錯誤日志輸出。程式直接crash掉。有多種原因造成這種沒有 錯誤日志輸出的情況。大緻可以有 :1: 使用了斷言(注意不是斷點)。2:_objc_sendMessage not found Object ( 某一對象被提前釋放 )。

下面給一個例子(為了造成對象提前被釋放,使用mrc手動管理記憶體比較易于實作demo),程式crash 但是沒有任何的錯誤日志輸出。

BtnView 類

#import <UIKit/UIKit.h>

@interface BtnView : UIView

-(void)test;

@end
           
#import "BtnView.h"

@implementation BtnView

-(instancetype)initWithFrame:(CGRect)frame
{
    if(self=[super initWithFrame:frame]){
        
       
        
    }
    return self;
}



-(void)test
{
    NSLog(@"_objc_sendMessage not found Object");
}


@end
           

ViewController

#import "ViewController.h"
#import "BtnView.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    
    BtnView *btnView=[[BtnView alloc] initWithFrame:CGRectMake(10, 50, self.view.bounds.size.width-20, 40)];
    [self.view addSubview:btnView];
    [btnView release];
    [btnView release];
    
    UIButton *btn=[UIButton buttonWithType:UIButtonTypeSystem];
    [btn setTitle:@"對象被釋放,測試僵屍環境變量" forState:UIControlStateNormal];
    btn.frame=CGRectMake(10, 50, self.view.bounds.size.width-20, 40);
    [btn addTarget:btnView action:@selector(test) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:btn];
    [btn release];
    
    
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end
           

程式bulid 成功,允許,點選按鍵:程式 崩潰,但沒有任何錯誤日志輸出,隻提示EXC_BAD_ACCESS:(當然如果你是一名老手,一眼就能看出EXC_BAD_ACCESS 一般都是由于向已經銷毀的對象發送資訊時 給出的錯誤)

利用 僵屍環境變量 找出Crash原因( 僵屍斷點 )
利用 僵屍環境變量 找出Crash原因( 僵屍斷點 )

那麼 遇到這種情況?我們如何來調試程式呢?

這就要使用到 僵屍環境變量了 --- NSZombieEnabled

至于NSZombieEnabled,就是當設定NSZombieEnabled環境變量後,一個對象銷毀時會被轉化為_NSZombie,該對象隻會被标記為“釋放”但卻仍然被保留在記憶體當中。如此一來,當我們通路某個僵屍對象時,Xcode會提醒我們該對象雖然能夠被通路、但在實際環境中已經不應存在。在這種模式下,我們将能夠了解到正常情況下無法獲得的實時狀态與對象位置。設定NSZombieEnabled後,當你向一個已經釋放的對象發送消息,這個對象就不會向之前那樣Crash或者産生 一個難以了解的行為,而是放出一個錯誤消息,然後以一種可預測的可以産生debug斷點的方式消失(原文是die),是以我們就可以找到具體或者大概是哪 個對象被錯誤的釋放了。

如何在xcode中配置 僵屍環境 變量呢?

Product -> Scheme -> Edit Scheme -> Environment Variables -> 添加一個僵屍環境變量:NSZombieEnabled  值設為 Yes 同時保證環境變量被使用(也就是前面的 勾 要選上)

1:

利用 僵屍環境變量 找出Crash原因( 僵屍斷點 )

2:

利用 僵屍環境變量 找出Crash原因( 僵屍斷點 )

3:

利用 僵屍環境變量 找出Crash原因( 僵屍斷點 )

4:

利用 僵屍環境變量 找出Crash原因( 僵屍斷點 )

僵屍環境 變量配置完成後,這時候,我們再允許程式,點選按鍵,就會有錯誤日志 跟蹤堆棧的資訊輸出:

利用 僵屍環境變量 找出Crash原因( 僵屍斷點 )

最後在附上一篇其他排除bug的文章:http://mobile.51cto.com/iphone-377138.htm