Skip to content

Instantly share code, notes, and snippets.

@wuchuwuyou
Last active August 8, 2018 10:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save wuchuwuyou/fdd20f64510e7652c7d95f5a22b7d988 to your computer and use it in GitHub Desktop.
Save wuchuwuyou/fdd20f64510e7652c7d95f5a22b7d988 to your computer and use it in GitHub Desktop.
crash report 崩溃记录
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
InstallSignalHandler();
InstallUncaughtExceptionHandler();
}
typedef struct Test
{
int a;
int b;
}Test;
- (void)signalCrash {
Test *pTest = {1,2};
free(pTest);//导致SIGABRT的错误,因为内存中根本就没有这个空间,哪来的free,就在栈中的对象而已
pTest->a = 5;
}
- (void)expCrash {
NSArray *array= @[@"tom",@"xxx",@"ooo"];
[array objectAtIndex:5];
}
void InstallSignalHandler(void);
void InstallUncaughtExceptionHandler(void);
@interface LBUncaughtExceptionHandler : NSObject
@end
@interface LBUncaughtException : NSObject
//- (void)installUncaughtExceptionHandler;
@end
#import "LBUncaughtExceptionHandler.h"
#include <libkern/OSAtomic.h>
#include <execinfo.h>
@implementation LBUncaughtExceptionHandler
NSString *applicationDocumentsDirectory() {
return [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
}
void UncaughtExceptionHandler(NSException *exception) {
NSArray *arr = [exception callStackSymbols];
NSString *reason = [exception reason];
NSString *name = [exception name];
NSDictionary *userInfo = [exception userInfo];
NSString *dataString = [NSString stringWithFormat:@"=============异常崩溃报告=============\nname:\n%@\nreason:\n%@\ncallStackSymbols:\n%@\nuserInfo:%@\n",
name,reason,[arr componentsJoinedByString:@"\n"],userInfo];
NSData *data = [dataString dataUsingEncoding:NSUTF8StringEncoding];
writInfo(data);
}
void writInfo(NSData *data) {
NSString *fileName = [NSString stringWithFormat:@"%0.0f.crash",[[NSDate date] timeIntervalSince1970]*1000];
NSString *filePath = [NSString stringWithFormat:@"/aaa/bbb/Crash/%@",fileName];
NSString *path = [applicationDocumentsDirectory() stringByAppendingPathComponent:filePath];
writeInfoWithPath(data, path);
}
void writeInfoWithPath(NSData *data,NSString *path) {
NSFileManager *fileManager = [NSFileManager defaultManager];
if (![fileManager fileExistsAtPath:[path stringByDeletingLastPathComponent]]) {
[fileManager createDirectoryAtPath:[path stringByDeletingLastPathComponent] withIntermediateDirectories:YES attributes:nil error:nil];
}
[fileManager createFileAtPath:path contents:data attributes:nil];
}
@end
@implementation LBUncaughtException
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;
void InstallSignalHandler() {
signal(SIGABRT, LBSignalHandler);
signal(SIGILL, LBSignalHandler);
signal(SIGSEGV, LBSignalHandler);
signal(SIGFPE, LBSignalHandler);
signal(SIGBUS, LBSignalHandler);
signal(SIGPIPE, LBSignalHandler);
}
void InstallUncaughtExceptionHandler(){
NSSetUncaughtExceptionHandler(&UncaughtExceptionHandler);
}
+ (NSArray *)getBacktrace {
void *callStack[128];//堆栈方法数组
int frames=backtrace(callStack, 128);//从iOS的方法backtrace中获取错误堆栈方法指针数组,返回数目
char **strs=backtrace_symbols(callStack, frames);//符号化
int i;
NSMutableArray *symbolsBackTrace=[NSMutableArray arrayWithCapacity:frames];
for (i=0; i<frames; i++) {
[symbolsBackTrace addObject:[NSString stringWithUTF8String:strs[i]]];
}
free(strs);
return symbolsBackTrace;
}
void handleSignalException(NSException *exception) {
CFRunLoopRef runLoop = CFRunLoopGetCurrent();
CFArrayRef allModes = CFRunLoopCopyAllModes(runLoop);
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]) {
UncaughtExceptionHandler(exception);
kill(getpid(), [[[exception userInfo] objectForKey:UncaughtExceptionHandlerSignalKey] intValue]);
} else {
[exception raise];
}
}
NSString* getAppInfo() {
NSString *appInfo = [NSString stringWithFormat:@"App : %@ %@(%@)\n",
[[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleDisplayName"],
[[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"],
[[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleVersion"]];
NSLog(@"Crash!!!! %@", appInfo);
return appInfo;
}
void LBSignalHandler(int signal) {
int32_t exceptionCount = OSAtomicIncrement32(&UncaughtExceptionCount);
if (exceptionCount > UncaughtExceptionMaximum) {
return;
}
NSMutableDictionary *userInfo = [NSMutableDictionary dictionaryWithObject:[NSNumber numberWithInt:signal] forKey:UncaughtExceptionHandlerSignalKey];
NSArray *callStack = [LBUncaughtException getBacktrace];
[userInfo setObject:callStack forKey:UncaughtExceptionHandlerAddressesKey];
NSException *signalException=[NSException exceptionWithName:UncaughtExceptionHandlerSignalExceptionName reason:[NSString stringWithFormat:@"Signal %d was raised.",signal] userInfo:userInfo];
// UncaughtExceptionHandler(signalException);
handleSignalException(signalException);
// NSArray *callStack = [LBUncaughtException getBacktrace];
// NSString *content = [callStack componentsJoinedByString:@"\n"];
// writInfo([content dataUsingEncoding:NSUTF8StringEncoding]);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment