美文网首页
iOS 崩溃异常捕获

iOS 崩溃异常捕获

作者: 黑暗森林的歌者 | 来源:发表于2016-07-21 15:37 被阅读309次

iOS已经提供了捕获异常的机制

NSSetUncaughtExceptionHandler

我们就创建一个捕获crash的类,其中写好分析崩溃原因的方法

头文件

#import <UIKit/UIKit.h>

@interface UncaughtExceptionHandler : NSObject{

}

@end

void HandleException(NSException *exception);
void SignalHandler(int signal);

//在didFinishLaunchingWithOptions中添加这个方法
//添加一行  
/*
  InstallUncaughtExceptionHandler();
*/
void InstallUncaughtExceptionHandler(void);

.m文件

定义

#include <libkern/OSAtomic.h>
#include <execinfo.h>

NSString * const UncaughtExceptionHandlerSignalExceptionName = @"UncaughtExceptionHandlerSignalExceptionName";
NSString * const UncaughtExceptionHandlerSignalKey = @"UncaughtExceptionHandlerSignalKey";
NSString * const UncaughtExceptionHandlerAddressesKey = @"UncaughtExceptionHandlerAddressesKey";

volatile int32_t UncaughtExceptionCount = 0;
const int32_t UncaughtExceptionMaximum = 10;

const NSInteger UncaughtExceptionHandlerSkipAddressCount = 4;
const NSInteger UncaughtExceptionHandlerReportAddressCount = 5;

实现方法

@implementation UncaughtExceptionHandler

+ (NSArray *)backtrace
{
  void* callstack[128];
  int frames = backtrace(callstack, 128);
  char **strs = backtrace_symbols(callstack, frames);
  
  int i;
  NSMutableArray *backtrace = [NSMutableArray arrayWithCapacity:frames];
  for (
   i = UncaughtExceptionHandlerSkipAddressCount;
   i < UncaughtExceptionHandlerSkipAddressCount +
   UncaughtExceptionHandlerReportAddressCount;
  i++)
  {
   [backtrace addObject:[NSString stringWithUTF8String:strs[i]]];
  }
  free(strs);
  
  return backtrace;
}
- (void)handleException:(NSException *)exception
{
 //可以在这个方法中打印或者弹出alert显示出来错误信息
/*弹窗的message可以是
  [NSString stringWithFormat:NSLocalizedString(   
                @"你可以执行一些崩溃后需要做的事情.\n"  
                @"%@\n%@", nil),  
                [exception reason],    //崩溃内容 
                [[exception userInfo] objectForKey:UncaughtExceptionHandlerAddressesKey]]
*/
 CFRunLoopRef runLoop = CFRunLoopGetCurrent();
 CFArrayRef allModes = CFRunLoopCopyAllModes(runLoop);
 while (!dismissed)
 {
  for (NSString *mode in (NSArray *)allModes)
  {
   CFRunLoopRunInMode((CFStringRef)mode, 0.001, false);
  }
 }
 CFRelease(allModes);

 NSSetUncaughtExceptionHandler(NULL);
 signal(SIGABRT, SIG_DFL);
 signal(SIGILL, SIG_DFL);
 signal(SIGSEGV, SIG_DFL);
 signal(SIGFPE, SIG_DFL);
 signal(SIGBUS, SIG_DFL);
 signal(SIGPIPE, SIG_DFL);
 
    {
        kill(getpid(),[[[[exception userInfo] allValues] lastObject] intValue]);
    }

}

@end
void HandleException(NSException *exception)
{
 int32_t exceptionCount = OSAtomicIncrement32(&UncaughtExceptionCount);
 if (exceptionCount > UncaughtExceptionMaximum)
 {
  return;
 }
 
 NSArray *callStack = [exception callStackSymbols];//堆栈调用信息
    //[UncaughtExceptionHandler backtrace];
 NSMutableDictionary *userInfo =
  [NSMutableDictionary dictionaryWithDictionary:[exception userInfo]];
 [userInfo
  setObject:callStack
  forKey:UncaughtExceptionHandlerAddressesKey];
 
 [[[[UncaughtExceptionHandler alloc] init] autorelease]
  performSelectorOnMainThread:@selector(handleException:)
  withObject:
   [NSException
    exceptionWithName:[exception name]
    reason:[exception reason]
    userInfo:userInfo]
  waitUntilDone:YES];
}

void SignalHandler(int signal)
{
      NSLog(@"handleException 4");
 int32_t exceptionCount = OSAtomicIncrement32(&UncaughtExceptionCount);
 if (exceptionCount > UncaughtExceptionMaximum)
 {
  return;
 }
 
 NSMutableDictionary *userInfo =
  [NSMutableDictionary
   dictionaryWithObject:[NSNumber numberWithInt:signal]
   forKey:UncaughtExceptionHandlerSignalKey];

 NSArray *callStack = [UncaughtExceptionHandler backtrace];
 [userInfo
  setObject:callStack
  forKey:UncaughtExceptionHandlerAddressesKey];
 
 [[[[UncaughtExceptionHandler alloc] init] autorelease]
  performSelectorOnMainThread:@selector(handleException:)
  withObject:
   [NSException
    exceptionWithName:UncaughtExceptionHandlerSignalExceptionName
    reason:
     [NSString stringWithFormat:
      NSLocalizedString(@"Signal %d was raised.", nil),
      signal]
    userInfo:
     [NSDictionary
      dictionaryWithObject:[NSNumber numberWithInt:signal]
      forKey:UncaughtExceptionHandlerSignalKey]]
  waitUntilDone:YES];
}

void InstallUncaughtExceptionHandler(void)
{
 NSSetUncaughtExceptionHandler(&HandleException);
 signal(SIGABRT, SignalHandler);
 signal(SIGILL, SignalHandler);
 signal(SIGSEGV, SignalHandler);
 signal(SIGFPE, SignalHandler);
 signal(SIGBUS, SignalHandler);
 signal(SIGPIPE, SignalHandler);
}

相关文章

  • iOS Crash 大解析

    iOS crash / 崩溃/ 异常 /捕获 1 崩溃日志(crash log) Xcode中 查看崩溃信息 手...

  • iOS Crash 流程化0:概览

    Ref:iOS Crash 捕获及堆栈符号化思路剖析 iOS Crash 流程化:概览崩溃捕获Mach 异常捕获U...

  • iOS 之 APP 异常崩溃抓取

    iOS 之 APP 异常崩溃抓取 NSSetUncaughtExceptionHandler 自己用程序捕获 cr...

  • iOS崩溃异常捕获

    最近项目上需要对崩溃信息进行处理,要满足崩溃后及时捕捉到崩溃信息,当应用下次打开后再将报文上传至服务器...

  • iOS 崩溃异常捕获

    iOS已经提供了捕获异常的机制 NSSetUncaughtExceptionHandler 我们就创建一个捕获cr...

  • iOS捕获崩溃异常

    在开发中经常会遇到崩溃的情况,在调试过程中可以直接看到崩溃信息,但是发布之后查看崩溃信息就比较困难了。iOS提供了...

  • Android 如何捕获崩溃异常并重启应用

    第一种方法:通过AppUncaughtExceptionHandler来捕获异常 Android全局捕获崩溃异常记...

  • Crash 捕获及堆栈符号化思路

    崩溃捕获 崩溃主要是由于 Mach 异常、Objective-C 异常(NSException)引起的,同时对于 ...

  • XCode中main.m直接crash

    问题描述 解决方法xcode gdb/lldb调试命令ps:主要学到的是btios崩溃的解决iOS捕获异常,常用的...

  • 2019-05-05

    一 、异常捕获 1.异常捕获 正常情况下程序出现异常,程序会直接崩溃,不能接着往后面执行。异常捕获就是为了程序出现...

网友评论

      本文标题:iOS 崩溃异常捕获

      本文链接:https://www.haomeiwen.com/subject/nhpbjttx.html