iOS Crash闪退信息捕获工具类

jopen 10年前

        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