IOS SDK中提供了一个现成的函数 NSSetUncaughtExceptionHandler 用来做异常处理,但功能非常有限,而引起崩溃的大多数原因如:内存访问错误,重复释放等错误捕获不到,因为这些异常抛出的是Signal,所以必须要专门做Signal处理。工具类的实现源码如下:
头文件
1
2
3
4
5
6
7
8
9
10
|
#
import
<foundation foundation.h=
""
>
extern NSString *
const
UncaughtExceptionHandlerSignalKey;
extern NSString *
const
SingalExceptionHandlerAddressesKey;
extern NSString *
const
ExceptionHandlerAddressesKey;
@interface
ExceptionHandler : NSObject
+ (
void
)installExceptionHandler;
+ (NSArray *)backtrace;
@end
|
实现文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
|
#
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
|