您的位置:首页 > 移动开发 > IOS开发

iOS应用崩溃(三)——崩溃日志

2015-12-27 00:42 337 查看

一、模拟器上显示堆栈信息

当我们在模拟器上调试时,可能经常遇到下面的内存访问错误:

2011-01-17 20:21:11.41 App[26067:207] * -[Testedit retain]: message sent to deallocated instance 0x12e4b

该错误是对一个已经释放的对象进行操作,定位如下:

(1)、设置MallocStackLogging:

①、点击Xcode的Product菜单,选择Edit Scheme…选项

②、选择左侧的Run…,右边点击Arguments

③、在Environment Variables栏里,添加NSZombieEnabled,value为YES;再添加MallocStackLogging,value为YES;

如下图所示:



以上选项只能在模拟器上有效,如果你改变了iOS的版本,需要重新设定。

调试结束后,最好记得把环境变量NSZombieEnabled,MallocStackLogging前面的勾去掉,因为它们会使得内存不会被释放.

(2)、终端输入 info malloc-history 命令,即可得到堆栈信息,从而分析具体问题所在

(gdb) info malloc-history 0x12e4b0


(3)、也可输入如下信息:

(gdb) shell malloc_history {pid/partial-process-name} {address}


PS:内存使用时“EXC_BAD_ACCESS”的错误信息也是经常遇到的,这时我们只要将上面执行文件属性中的 NSZombieEnabled 选上,也能定位该问题。

二、在iPhone上输出日志

iOS开发中我们会遇到程序抛出异常退出的情况,如果是在调试的过程中,异常的信息是一目了然,但是如果是在已经发布的程序中,获取异常的信息有时候是比较困难的。

1、可以捕捉的异常(ECX_CRASH)

iOS提供了异常发生的处理API,我们在程序启动的时候可以添加这样的Handler,这样的程序发生异常的时候就可以对一部分的信息进行必要的处理,适时的反馈给开发者。NSException导致程序向自身发送了SIGABRT信号而崩溃;SIGABRT(也叫做ECX_CRASH)是一个比较好解决的Crash,以为他是一个可掌控的crash,App会在一个目的地终止,以为系统意识到app做了一些他不能支持的事情。

接口声明:

#import <Foundation/Foundation.h>
@interface NdUncaughtExceptionHandler : NSObject
+ (void)setDefaultHandler;
+ (NSUncaughtExceptionHandler*)getHandler;
@end


接口实现:

#import "NdUncaughtExceptionHandler.h"
//返回绝对路径
NSString *applicationDocumentsDirectory() {
return [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
}
void UncaughtExceptionHandler(NSException *exception) {
NSArray *arr = [exception callStackSymbols];
NSString *reason = [exception reason];
NSString *name = [exception name];
NSString *url = [NSString stringWithFormat:@"=============异常崩溃报告=============\nname:\n%@\nreason:\n%@\ncallStackSymbols:\n%@",
name,reason,[arr componentsJoinedByString:@"\n"]];
NSString *path = [applicationDocumentsDirectory() stringByAppendingPathComponent:@"Exception.txt"];
[url writeToFile:path atomically:YES encoding:NSUTF8StringEncoding error:nil];
//除了可以选择写到应用下的某个文件,通过后续处理将信息发送到服务器等
//还可以选择调用发送邮件的的程序,发送信息到指定的邮件地址
//或者调用某个处理程序来处理这个信息
}
@implementation NdUncaughtExceptionHandler
//返回绝对路径
-(NSString *)applicationDocumentsDirectory {
return [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
}
+ (void)setDefaultHandler
{
NSSetUncaughtExceptionHandler (&UncaughtExceptionHandler);
}
+ (NSUncaughtExceptionHandler*)getHandler
{
return NSGetUncaughtExceptionHandler();
}
@end


调用事例:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[NdUncaughtExceptionHandler setDefaultHandler];
NSArray *array = [NSArray arrayWithObject:@"there is only one objective in this arary,call index one, app will crash and throw an exception!"];
NSLog(@"%@", [array objectAtIndex:1]);
return YES;
}


崩溃信息如下:

=============异常崩溃报告=============
name:
NSRangeException
reason:
*** -[__NSArrayI objectAtIndex:]: index 1 beyond bounds [0 .. 0]
callStackSymbols:
0   CoreFoundation                      0x0000000108573c65 __exceptionPreprocess + 165
1   libobjc.A.dylib                     0x000000010820cbb7 objc_exception_throw + 45
2   CoreFoundation                      0x000000010846a17e -[__NSArrayI objectAtIndex:] + 190
3   UIColorDemo                         0x0000000107c88914 -[AppDelegate application:didFinishLaunchingWithOptions:] + 164
4   UIKit                               0x00000001090be748 -[UIApplication _handleDelegateCallbacksWithOptions:isSuspended:restoreState:] + 240
5   UIKit                               0x00000001090bf357 -[UIApplication _callInitializationDelegatesForMainScene:transitionContext:] + 2540
6   UIKit                               0x00000001090c219e -[UIApplication _runWithMainScene:transitionContext:completion:] + 1349
7   UIKit                               0x00000001090c1095 -[UIApplication workspaceDidEndTransaction:] + 179
8   FrontBoardServices                  0x000000010dd095e5 __31-[FBSSerialQueue performAsync:]_block_invoke_2 + 21
9   CoreFoundation                      0x00000001084a741c __CFRUNLOOP_IS_CALLING_OUT_TO_A_BLOCK__ + 12
10  CoreFoundation                      0x000000010849d165 __CFRunLoopDoBlocks + 341
11  CoreFoundation                      0x000000010849c947 __CFRunLoopRun + 887
12  CoreFoundation                      0x000000010849c366 CFRunLoopRunSpecific + 470
13  UIKit                               0x00000001090c0b02 -[UIApplication _run] + 413
14  UIKit                               0x00000001090c38c0 UIApplicationMain + 1282
15  UIColorDemo                         0x0000000107c88e4f main + 111
16  libdyld.dylib                       0x000000010afcc145 start + 1
17  ???                                 0x0000000000000001 0x0 + 1


2、内存等导致的异常(EXC_BAD_ACCESS)

引起崩溃的大多数原因如:内存访问错误(访问了不属于本进程的内存地址),重复释放错误等;EXC_BAD_ACCESS是一个比较难处理的crash了,当一个app进入一种毁坏的状态,通常是由于内存管理问题而引起的时,就会出现出现这样的crash。这种错误它抛出的是Signal,上述方法无法捕捉到。所以必须要专门做Signal处理。

代码如下:
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: