IOS SDK中提供了一个现成的函数 NSSetUncaughtExceptionHandler 用来做异常处理,但功能非常有限,而引起崩溃的大多数原因如:内存访问错误,重复释放等错误捕获不到,因为这些异常抛出的是Signal,所以必须要专门做Signal处理。工具类的实现源码如下:
头文件
#import <Foundation/Foundation.h> extern NSString *const UncaughtExceptionHandlerSignalKey; extern NSString *const SingalExceptionHandlerAddressesKey; extern NSString *const ExceptionHandlerAddressesKey; @interface ExceptionHandler : NSObject + (void)installExceptionHandler; + (NSArray *)backtrace; @end
实现文件
#import "ExceptionHandler.h" #include <libkern/OSAtomic.h> #include <execinfo.h> NSString *const UncaughtExceptionHandlerSignalKey = @"UncaughtExceptionHandlerSignalKey"; NSString *const SingalExceptionHandlerAddressesKey = @"SingalExceptionHandlerAddressesKey"; NSString *const ExceptionHandlerAddressesKey = @"ExceptionHandlerAddressesKey"; const int32_t _uncaughtExceptionMaximum = 20; // 系统信号截获处理方法 void signalHandler(int signal); // 异常截获处理方法 void exceptionHandler(NSException *exception); void signalHandler(int signal) { volatile int32_t _uncaughtExceptionCount = 0; int32_t exceptionCount = OSAtomicIncrement32(&_uncaughtExceptionCount); // 如果太多不用处理 if (exceptionCount > _uncaughtExceptionMaximum) { return; } // 获取信息 NSMutableDictionary *userInfo = [NSMutableDictionary dictionaryWithObject:[NSNumber numberWithInt:signal] forKey:UncaughtExceptionHandlerSignalKey]; NSArray *callStack = [ExceptionHandler backtrace]; [userInfo setObject:callStack forKey:SingalExceptionHandlerAddressesKey]; // 现在就可以保存信息到本地[] } void exceptionHandler(NSException *exception) { volatile int32_t _uncaughtExceptionCount = 0; int32_t exceptionCount = OSAtomicIncrement32(&_uncaughtExceptionCount); // 如果太多不用处理 if (exceptionCount > _uncaughtExceptionMaximum) { return; } NSArray *callStack = [ExceptionHandler backtrace]; NSMutableDictionary *userInfo =[NSMutableDictionary dictionaryWithDictionary:[exception userInfo]]; [userInfo setObject:callStack forKey:ExceptionHandlerAddressesKey]; NSLog(@"Exception Invoked: %@", userInfo); // 现在就可以保存信息到本地[] } @implementation ExceptionHandler //获取调用堆栈 + (NSArray *)backtrace { void* callstack[128]; int frames = backtrace(callstack, 128); char **strs = backtrace_symbols(callstack,frames); NSMutableArray *backtrace = [NSMutableArray arrayWithCapacity:frames]; for (int i=0;i<frames;i++) { [backtrace addObject:[NSString stringWithUTF8String:strs[i]]]; } free(strs); return backtrace; } // 注册崩溃拦截 + (void)installExceptionHandler { NSSetUncaughtExceptionHandler(&exceptionHandler); signal(SIGHUP, signalHandler); signal(SIGINT, signalHandler); signal(SIGQUIT, signalHandler); signal(SIGABRT, signalHandler); signal(SIGILL, signalHandler); signal(SIGSEGV, signalHandler); signal(SIGFPE, signalHandler); signal(SIGBUS, signalHandler); signal(SIGPIPE, signalHandler); } @end