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