您的位置:首页 > 其它

利用 僵尸环境变量 找出Crash原因( 僵尸断点 )

2015-06-13 14:08 375 查看
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
一般都是由于向已经销毁的对象发送信息时 给出的错误)





那么 遇到这种情况?我们如何来调试程序呢?

这就要使用到 僵尸环境变量了 --- NSZombieEnabled

至于NSZombieEnabled,就是当设置NSZombieEnabled环境变量后,一个对象销毁时会被转化为_NSZombie,该对象只会被标记为“释放”但却仍然被保留在内存当中。如此一来,当我们访问某个僵尸对象时,Xcode会提醒我们该对象虽然能够被访问、但在实际环境中已经不应存在。在这种模式下,我们将能够了解到正常情况下无法获得的实时状态与对象位置。设置NSZombieEnabled后,当你向一个已经释放的对象发送消息,这个对象就不会向之前那样Crash或者产生
一个难以理解的行为,而是放出一个错误消息,然后以一种可预测的可以产生debug断点的方式消失(原文是die),因此我们就可以找到具体或者大概是哪 个对象被错误的释放了。

如何在xcode中配置 僵尸环境 变量呢?

Product -> Scheme -> Edit Scheme -> Environment Variables -> 添加一个僵尸环境变量:NSZombieEnabled 值设为 Yes
同时保证环境变量被使用(也就是前面的 勾 要选上)

1:



2:



3:



4:



僵尸环境 变量配置完成后,这时候,我们再允许程序,点击按键,就会有错误日志 跟踪堆栈的信息输出:



最后在附上一篇其他排除bug的文章:http://mobile.51cto.com/iphone-377138.htm
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: