iOS異常捕獲和處理

2013年4月份整理的代碼,僅做記錄:
 

//先宏定義
//發佈和未發佈狀態的日誌切換
#ifdef DEBUG
    //異常棧開關
    #define STACK_KEY YES
    //日誌重定向開關
    #define STDERR_KEY NO
    //調試日誌
    #define DebugLog(format,...)    NSLog(@"{%s,%d}" format, __FUNCTION__,__LINE__,##__VA_ARGS__)
    //異常棧日誌
    #define StackLog(format,...)    NSLog(@"{%s,%d}" format, __FUNCTION__,__LINE__,##__VA_ARGS__)
    //輸出日至
    #define DLOG(...)   NSLog(__VA_ARGS__)
    //輸出詳細日誌
    #define DLOGEXT(fmt, ...) NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__);
    //輸出調用
    #define DLOGCALL DLOG(@"[%@ %@]", NSStringFromClass([self class]), NSStringFromSelector(_cmd))
    //輸出方法
    #define DLOGMETHODNSLog(@"[%s] %@", class_getName([self class]), NSStringFromSelector(_cmd));
    //輸出點
    #define DLOGPOINT(p)NSLog(@"%f,%f", p.x, p.y);
    //輸出大小
    #define DLOGSIZE(p)NSLog(@"%f,%f", p.width, p.height);
    //輸出矩形
    #define DLOGRECT(p)NSLog(@"%f,%f %f,%f", p.origin.x, p.origin.y, p.size.width, p.size.height);
#else
    #define STACK_KEY YES
    #define STDERR_KEY YES
    #define DebugLog(format,...)
    #define StackLog(format,...)
    #define DLOG(...)
    #define DLOGEXT(...)
    #define DLOGCALL
    #define DLOGMETHOD
    #define DLOGPOINT(p)
    #define DLOGSIZE(p)
    #define DLOGRECT(p)
#endif
 

AppDelegate的- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions中加入如下代碼:
 
 
 
    //設置異常日誌文件
    if (STDERR_KEY) {
         NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
        NSString *documentDir = [paths objectAtIndex:0];
        NSString *decyStr = [NSString stringWithFormat:@"decrypt.log"];
        NSString *logPath = [documentDir stringByAppendingPathComponent:decyStr];
        freopen([logPath cStringUsingEncoding:NSASCIIStringEncoding], "w+", stderr);
    }
   
    //異常棧
    if (STACK_KEY) {
        //設置處理異常的Handler
        NSSetUncaughtExceptionHandler(&UncaughtExceptionHandler);
       
        //signal處理機制
        struct sigaction mySigAction;
        mySigAction.sa_sigaction = stacktrace;
        mySigAction.sa_flags = SA_SIGINFO;
       
        sigemptyset(&mySigAction.sa_mask);
        sigaction(SIGQUIT, &mySigAction, NULL);
        sigaction(SIGILL , &mySigAction, NULL);
        sigaction(SIGTRAP, &mySigAction, NULL);
        sigaction(SIGABRT, &mySigAction, NULL);
        sigaction(SIGEMT , &mySigAction, NULL);
        sigaction(SIGFPE , &mySigAction, NULL);
        sigaction(SIGBUS , &mySigAction, NULL);
        sigaction(SIGSEGV, &mySigAction, NULL);
        sigaction(SIGSYS , &mySigAction, NULL);
        sigaction(SIGPIPE, &mySigAction, NULL);
        sigaction(SIGALRM, &mySigAction, NULL);
        sigaction(SIGXCPU, &mySigAction, NULL);
        sigaction(SIGXFSZ, &mySigAction, NULL);
    }
 
 

並在同個頁面中實現如下方法:
 
//異常處理
#pragma mark - DebugMethods
void UncaughtExceptionHandler(NSException *exception) {
    StackLog(@"receive a UncaughtExceptionHandler");
    NSArray *arr = [exception callStackSymbols];
    NSString *reason = [exception reason];
    NSString *name = [exception name];
    NSString *syserror = [NSStringstringWithFormat:@"UncaughtExceptionHandlerName:%@\nUncaughtExceptionHandlerReason:%@\nUncaughtExceptionHandlerArray:%@",name, reason, arr];
    StackLog(@"%@", syserror);
}
void stacktrace(int sig, siginfo_t *info, void *context)
{
    
    NSMutableString * mstr = [[[NSMutableStringalloc] initWithCapacity:0] autorelease];
    [mstr appendString:@"Stack:\n"];
    StackLog(@"sig %d",sig);
    
    void* callstack[128];
    int i, frameCount = backtrace(callstack, 128);
    char** strs = backtrace_symbols(callstack, frameCount);
    for (i = 0; i < frameCount; ++i) {
        [mstr appendFormat:@"%s\n", strs[i]];
    }
    
    StackLog(@"Stack Trace:\r\n%@", mstr);
}
相關文章
相關標籤/搜索