IOS程序异常crash捕获与拦截
来源:互联网 发布:linux expect telnet 编辑:程序博客网 时间:2024/03/29 18:19
开发iOS应用,解决Crash问题始终是一个难题。Crash分为两种,一种是由EXC_BAD_ACCESS引起的,原因是访问了不属于本进程的内存地址,有可能是访问已被释放的内存;另一种是未被捕获的Objective-C异常(NSException),导致程序向自身发送了SIGABRT信号而崩溃。其实对于未捕获的Objective-C异常,我们是有办法将它记录下来的,如果日志记录得当,能够解决绝大部分崩溃的问题。这里对于UI线程与后台线程分别说明。
@interface UncaughtExceptionHandler : NSObject{
BOOL
dismissed;
}
@end
void
HandleException(NSException *exception);
void
SignalHandler(
int
signal
);
void
InstallUncaughtExceptionHandler(
void
);
//该代码片段来自于: http://www.sharejs.com/codes/objectc/5882
#import "UncaughtExceptionHandler.h"
#include <libkern/OSAtomic.h>
#include <execinfo.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]
autorelease];
[alert show];
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);
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] autorelease]
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] 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);
}
//该代码片段来自于: http://www.sharejs.com/codes/objectc/5882
- (
BOOL
)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
InstallUncaughtExceptionHandler();
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
// Override point for customization after application launch.
self.viewController = [[[ViewController alloc] initWithNibName:@
"ViewController"
bundle:nil] autorelease];
self.window.rootViewController = self.viewController;
[self.window makeKeyAndVisible];
return
YES;
}
//该代码片段来自于: http://www.sharejs.com/codes/objectc/5882
- (IBAction)onclcko:(id)sender {
// [alert show];
NSArray *arry=[NSArray arrayWithObject:@
"sss"
];
NSLog(@
"%@"
,[arry objectAtIndex:1]);
}
0 0
- iOS程序异常crash捕获与拦截
- [IOS]程序异常crash捕获与拦截
- IOS程序异常crash捕获与拦截
- IOS程序异常crash捕获与拦截
- IOS程序异常crash捕获与拦截
- IOS程序异常crash捕获与拦截
- IOS开发笔记 程序异常crash捕获与拦截
- 程序异常crash捕获与拦截
- IOS开发笔记(5)程序异常crash捕获与拦截
- IOS开发笔记(5)程序异常crash捕获与拦截
- IOS开发笔记(5)程序异常crash捕获与拦截
- IOS程序crash捕获
- ios 程序异常捕获
- iOS crash捕获异常崩溃日志
- iOS收集未捕获的异常,防止应用crash
- IOS Crash捕获
- IOS Crash捕获
- Android 中Crash捕获异常
- 例题10-19 概率 UVa11346
- iOS 使用gethostbyname() 解析域名得到IP
- java的list排序
- HDU 5175 Misaki's Kiss again(暴力枚举+异或运算)
- windows server 2008 R2 激活工具 - windows loader v2.1.7
- IOS程序异常crash捕获与拦截
- 使用ibatis nullvalue
- Unix环境高级编程学习笔记(七) 多线程
- Android.mk文件语法规范及使用模板
- 使用JQuery 合并两个 json 对象
- linux系统服务(2)----常用命令
- 安卓分享图片文字链接功能
- wait and waitpid
- Execution process of java program