美文网首页
Crash捕获

Crash捕获

作者: L柠_檬 | 来源:发表于2016-08-30 16:07 被阅读73次
1.1 捕获Crash日志
1.2 信号捕获方法

1.1  捕获Crash日志

- (BOOL)application:(UIApplication *)application 
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Override point for customization after application launch
    //方法调用
    [self installUncaugtExceptionHandler];

    return YES;
    
}
- (void)installUncaugtExceptionHandler{
    //捕获crash
     NSSetUncaughtExceptionHandler(&UncaughtExceptionhandler);
}

void UncaughtExceptionhandler(NSException *exception){
    //原因
    NSString *reason = [exception reason];
    //名字
    NSString *name = [exception name];
    NSString *currentVersion = [[[NSBundle 
   mainBundle]infoDictionary]objectForKey:@"CFBundleVersion"];
    NSLog(@"\n版本:%@\n名字:%@\n原因:%@",currentVersion,name,reason);
    //详细内容
    NSArray *arr = [exception callStackSymbols];
    NSLog(@"详细内容:%@",arr);



    测试:
    NSArray *a = @[@"1"];    
    NSLog(@"%@",a[10]);

    版本:1
    名字:NSRangeException
    原因:*** -[__NSArrayI objectAtIndex:]: index 10 beyond bounds [0 .. 0]

}

1.2 信号捕获方法

.h

#import <Foundation/Foundation.h>

@interface UncaughtExceptionHandler : NSObject{
    BOOL dismissed;
}

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


void InstallUncaughtExceptionHandler(void);


.m

#import "UncaughtExceptionHandler.h"
#include <libkern/OSAtomic.h>
#include <execinfo.h>
#import <UIKit/UIKit.h>
//http://www.cocoachina.com/newbie/tutorial/2012/0829/4672.html
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)alertView:(UIAlertView *)anAlertView 
clickedButtonAtIndex:(NSInteger)anIndex
{
    if (anIndex == 0)
    {
        dismissed = YES;
    }else if (anIndex==1) {
        NSLog(@"ssssssss");
    }
}

- (void)validateAndSaveCriticalApplicationData
{
    
}

- (void)handleException:(NSException *)exception
{
    [self validateAndSaveCriticalApplicationData];
    
    UIAlertView *alert =
    [[UIAlertView alloc]
      
    initWithTitle:NSLocalizedString(@"抱歉,程序出现了异常", nil)
      
    message:[NSString stringWithFormat:NSLocalizedString(
                                                          
   @"如果点击继续,程序有可能会出现其他的问题,建议您还是点击退出按钮并重新打开\n\n"
                                                          
   @"异常原因如下:\n%@\n%@", nil),
               [exception reason],
               [[exception userInfo] 
    objectForKey:UncaughtExceptionHandlerAddressesKey]]
      delegate:self
      cancelButtonTitle:NSLocalizedString(@"退出", nil)
      otherButtonTitles:NSLocalizedString(@"继续", nil), nil]
     ;
    [alert show];
    
    CFRunLoopRef runLoop = CFRunLoopGetCurrent();
    CFArrayRef allModes = CFRunLoopCopyAllModes(runLoop);
    
    while (!dismissed)
    {
        for (NSString *mode in (__bridge NSArray *)allModes)
        {
            CFRunLoopRunInMode((__bridge 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);
    
    if ([[exception name] 
    isEqual:UncaughtExceptionHandlerSignalExceptionName])
    {
        kill(getpid(), [[[exception userInfo] 
      objectForKey:UncaughtExceptionHandlerSignalKey] intValue]);
    }
    else
    {
        [exception raise];
    }
}

@end

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

void SignalHandler(int signal)
{
    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]
     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);
}


调用:
#import "AppDelegate.h"
#import "UncaughtExceptionHandler.h"

- (BOOL)application:(UIApplication *)application 
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Override point for customization after application launch
    InstallUncaughtExceptionHandler();

    return YES;
}

相关文章

  • iOS Crash 流程化0:概览

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

  • iOS Crash问题的捕获

    并不是所有的crash都可以捕获的NSException,如果捕获不到,可以使用signal机制来捕获Crash发...

  • iOS Swift Crash的捕获

    crash捕获介绍 如果对crash捕获不太了解,可以先参考这篇文章,本文进行Mach异常+Unix信号方式捕获c...

  • native crash相关小结

    一、native crash捕获原理 native crash捕获的原理摘选完善自:Android 开发中常见 C...

  • Crash捕获

  • Crash捕获

    纯粹为了记录这篇文章https://mp.weixin.qq.com/s?__biz=MjM5NTIyNTUyMQ...

  • iOS Mach异常和signal信号

    本着探究下iOS Crash捕获的目的,学习了下Crash捕获相关的Mach异常和signal信号处理,记录下相关...

  • Android crash捕获

    1.当应用发生crash时怎么捕获异常呢? 我们都知道,代码中使用try...catch可以捕获预知的crash,...

  • iOS Crash问题

    本文就捕获iOS Crash、Crash日志组成、Crash日志符号化、异常信息解读、常见的Crash五部分介绍。...

  • iOS Crash 大解析

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

网友评论

      本文标题:Crash捕获

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