iOS Crash閃退信息捕獲工具類 – iPhone手機開發技術文章 iPhone軟體開發教學課程

IOS SDK中提供瞭一個現成的函數 NSSetUncaughtExceptionHandler 用來做異常處理,但功能非常有限,而引起崩潰的大多數原因如:內存訪問錯誤,重復釋放等錯誤捕獲不到,因為這些異常拋出的是Signal,所以必須要專門做Signal處理。工具類的實現源碼如下:

頭文件

#import 

extern NSString *const UncaughtExceptionHandlerSignalKey;
extern NSString *const SingalExceptionHandlerAddressesKey;
extern NSString *const ExceptionHandlerAddressesKey;

@interface ExceptionHandler : NSObject
+ (void)installExceptionHandler;
+ (NSArray *)backtrace;
@end

實現文件

#import "ExceptionHandler.h"
#include
#include

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
</pre>

發佈留言