使用NSSetUncaughtExceptionHandler收集崩溃日志并分析

1. 在代码中添加手机崩溃日志代码

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    NSSetUncaughtExceptionHandler(&UncaughtExceptionHandler);
    [self updateAppErrorInfo];
    return YES;
}

#pragma mark    //如果有异常崩溃信息,提交异常
- (void)updateAppErrorInfo
{
    NSDictionary * dictionary = [NUD objectForKey:Sandbox_appErrorInfo];
    DLog(@"dictionary==%@",dictionary);
    //如果有异常崩溃信息,提交异常
    if (dictionary&&NotNilAndNull(dictionary[@"content"]))
    {
        static NSString *AppErrorBaseHostURL   =    @"http://:8080/appmanage/";//提交到自己的日志平台
        AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
        NSString * urlString   =   [[NSString stringWithFormat:@"%@%@",AppErrorBaseHostURL,@"/app/appErrorInfo/add"]stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLFragmentAllowedCharacterSet]];
        NSURL *URL = [NSURL URLWithString:urlString];
        manager.requestSerializer.timeoutInterval = 5.f;   //请求时间
        manager.requestSerializer   =   [AFHTTPRequestSerializer serializer];
        manager.responseSerializer  =   [AFHTTPResponseSerializer serializer];
        
        [manager POST:URL.absoluteString parameters:dictionary progress:^(NSProgress * _Nonnull downloadProgress) {
            
        } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nonnull responseObject) {

            
            NSDictionary * dic = [NSJSONSerialization JSONObjectWithData:responseObject options:NSJSONReadingAllowFragments error:nil];
            DLog(@"dic=========%@",dic);
            
            if ([dic[@"success"] isEqualToString:@"0"]) {
                [NUD removeObjectForKey:Sandbox_appErrorInfo];
            }
        } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
            
        }];

    }
}
#pragma mark    收集异常,存储到本地,下次用户打开程序时上传给我们
void UncaughtExceptionHandler(NSException *exception) {
    /**
     *  获取异常崩溃信息
     */
    NSArray *callStack = [exception callStackSymbols];
    NSString *reason = [exception reason];
    NSString *name = [exception name];
    
    NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
    [formatter setDateFormat:@"YYYY-MM-dd HH:mm:ss"];
    NSString * dateStr = [formatter stringFromDate:[NSDate date]];
    
    NSString * userID   =   [NUD objectForKey:USERID];
    NSString * userName =   [NUD objectForKey:USERNAME];
    
    NSString * iOS_Version = [[UIDevice currentDevice] systemVersion];
    NSString * PhoneSize    =   NSStringFromCGSize([[UIScreen mainScreen] bounds].size);
    
    NSString * App_Version = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"];
    NSString * iPhoneType = [RSToolNSObject getiPhoneType];
    
    NSString *content = [NSString stringWithFormat:@"%@
\niOS_Version : %@----PhoneSize : %@
\n----iPhoneType: %@
\nApp_Version : %@
\nuserID : %@
\nuserName : %@
\nname:%@
\nreason:\n%@
\ncallStackSymbols:\n%@",dateStr,iOS_Version,PhoneSize,iPhoneType,App_Version,userID,userName,name,reason,[callStack componentsJoinedByString:@"\n"]]; #if DEBUG NSDictionary * dictionary = @{@"content":content, @"isDebug":@(1), @"packageName":@"com.thinkjoy.NetworkTaxiDriver"}; #else NSDictionary * dictionary = @{@"content":content, @"isDebug":@(0), @"packageName":@"com.thinkjoy.NetworkTaxiDriver"}; #endif [NUD setObject:dictionary forKey:Sandbox_appErrorInfo]; } #pragma mark 获得设备型号 + (NSString *)getiPhoneType { struct utsname systemInfo; uname(&systemInfo); NSString *platform = [NSString stringWithCString:systemInfo.machine encoding:NSASCIIStringEncoding]; if ([platform isEqualToString:@"iPhone1,1"]) return @"iPhone 2G"; if ([platform isEqualToString:@"iPhone1,2"]) return @"iPhone 3G"; if ([platform isEqualToString:@"iPhone2,1"]) return @"iPhone 3GS"; if ([platform isEqualToString:@"iPhone3,1"]) return @"iPhone 4"; if ([platform isEqualToString:@"iPhone3,2"]) return @"iPhone 4"; if ([platform isEqualToString:@"iPhone3,3"]) return @"iPhone 4"; if ([platform isEqualToString:@"iPhone4,1"]) return @"iPhone 4S"; if ([platform isEqualToString:@"iPhone5,1"]) return @"iPhone 5"; if ([platform isEqualToString:@"iPhone5,2"]) return @"iPhone 5"; if ([platform isEqualToString:@"iPhone5,3"]) return @"iPhone 5c"; if ([platform isEqualToString:@"iPhone5,4"]) return @"iPhone 5c"; if ([platform isEqualToString:@"iPhone6,1"]) return @"iPhone 5s"; if ([platform isEqualToString:@"iPhone6,2"]) return @"iPhone 5s"; if ([platform isEqualToString:@"iPhone7,1"]) return @"iPhone 6 Plus"; if ([platform isEqualToString:@"iPhone7,2"]) return @"iPhone 6"; if ([platform isEqualToString:@"iPhone8,1"]) return @"iPhone 6s"; if ([platform isEqualToString:@"iPhone8,2"]) return @"iPhone 6s Plus"; if ([platform isEqualToString:@"iPhone8,4"]) return @"iPhone SE"; if ([platform isEqualToString:@"iPhone9,1"]) return @"iPhone 7"; if ([platform isEqualToString:@"iPhone9,2"]) return @"iPhone 7 Plus"; if ([platform isEqualToString:@"iPod1,1"]) return @"iPod Touch 1G"; if ([platform isEqualToString:@"iPod2,1"]) return @"iPod Touch 2G"; if ([platform isEqualToString:@"iPod3,1"]) return @"iPod Touch 3G"; if ([platform isEqualToString:@"iPod4,1"]) return @"iPod Touch 4G"; if ([platform isEqualToString:@"iPod5,1"]) return @"iPod Touch 5G"; if ([platform isEqualToString:@"iPad1,1"]) return @"iPad 1G"; if ([platform isEqualToString:@"iPad2,1"]) return @"iPad 2"; if ([platform isEqualToString:@"iPad2,2"]) return @"iPad 2"; if ([platform isEqualToString:@"iPad2,3"]) return @"iPad 2"; if ([platform isEqualToString:@"iPad2,4"]) return @"iPad 2"; if ([platform isEqualToString:@"iPad2,5"]) return @"iPad Mini 1G"; if ([platform isEqualToString:@"iPad2,6"]) return @"iPad Mini 1G"; if ([platform isEqualToString:@"iPad2,7"]) return @"iPad Mini 1G"; if ([platform isEqualToString:@"iPad3,1"]) return @"iPad 3"; if ([platform isEqualToString:@"iPad3,2"]) return @"iPad 3"; if ([platform isEqualToString:@"iPad3,3"]) return @"iPad 3"; if ([platform isEqualToString:@"iPad3,4"]) return @"iPad 4"; if ([platform isEqualToString:@"iPad3,5"]) return @"iPad 4"; if ([platform isEqualToString:@"iPad3,6"]) return @"iPad 4"; if ([platform isEqualToString:@"iPad4,1"]) return @"iPad Air"; if ([platform isEqualToString:@"iPad4,2"]) return @"iPad Air"; if ([platform isEqualToString:@"iPad4,3"]) return @"iPad Air"; if ([platform isEqualToString:@"iPad4,4"]) return @"iPad Mini 2G"; if ([platform isEqualToString:@"iPad4,5"]) return @"iPad Mini 2G"; if ([platform isEqualToString:@"iPad4,6"]) return @"iPad Mini 2G"; if ([platform isEqualToString:@"i386"]) return @"iPhone Simulator"; if ([platform isEqualToString:@"x86_64"]) return @"iPhone Simulator"; return platform; }

2. 收集到的崩溃日志如下

name:NSInvalidArgumentException
reason: *** -[__NSPlaceholderDictionary initWithObjects:forKeys:count:]: attempt to insert nil object from objects[0]
callStackSymbols: 0 CoreFoundation 0x2141a303 + 150 1 libobjc.A.dylib 0x20be6dff objc_exception_throw + 38 2 CoreFoundation 0x21337e2b + 342 3 CoreFoundation 0x21337caf + 50 4 NetworkTaxiDriver 0x0012ff29 NetworkTaxiDriver + 323369 5 NetworkTaxiDriver 0x0013019f NetworkTaxiDriver + 323999 6 UIKit 0x25695d29 + 2976 7 UIKit 0x2569507b + 378 8 UIKit 0x2569c995 + 328 9 UIKit 0x25735f45 + 488 10 NetworkTaxiDriver 0x0013013b NetworkTaxiDriver + 323899 11 UIKit 0x255b1d79 + 1028 12 UIKit 0x255b1959 + 24 13 UIKit 0x2566f4d5 + 280 14 UIKit 0x2566e8e5 + 96 15 UIKit 0x2566e51b + 834 16 UIKit 0x2566e16d + 52 17 UIKit 0x2566e0e7 + 214 18 UIKit 0x255ada83 + 714 19 QuartzCore 0x23689ad5 + 128 20 QuartzCore 0x236851d1 + 352 21 QuartzCore 0x23685061 + 16 22 QuartzCore 0x23684581 + 368 23 QuartzCore 0x23684233 + 614 24 UIKit 0x255b08d7 + 5518 25 CoreFoundation 0x213dd257 + 14 26 CoreFoundation 0x213dce47 + 454 27 CoreFoundation 0x213db1af + 806 28 CoreFoundation 0x2132dbb9 CFRunLoopRunSpecific + 516 29 CoreFoundation 0x2132d9ad CFRunLoopRunInMode + 108 30 GraphicsServices 0x225a7af9 GSEventRunModal + 160 31 UIKit 0x25619fb5 UIApplicationMain + 144 32 NetworkTaxiDriver 0x0013f46d NetworkTaxiDriver + 386157 33 libdyld.dylib 0x20fe0873 + 2
dSYM符号表获取

xcode->window->organizer->右键你的应用 show finder->右键.xcarchive 显示包内容->dSYMs->test.app.dYSM

atos命令

atos命令来符号化某个特定模块加载地址
atos [-arch 架构名] [-o 符号表] [-l 模块地址] [方法地址]

使用终端计算
1.没有模块地址,需要自己计算。
4   NetworkTaxiDriver                   0x00116f29 NetworkTaxiDriver + 323369
0x00116f29 = 1142569;   //将方法地主转化为十进制
1142569-323369 = 819200;//减去偏移地址,得到模块地址
819200 = 0xc8000;  //得到的模块地址在转为十六进制

终端示例:

//打开文件
cd /Users/thinkjoy/Desktop/出租车/出租车V1.6崩溃分析/NetworkTaxiDriver.app.dSYM 
//根据模块地址和方法地址计算问题代码位置
atos -arch armv7 -o /Users/thinkjoy/Desktop/出租车/出租车V1.6崩溃分析/NetworkTaxiDriver.app.dSYM/Contents/Resources/DWARF/NetworkTaxiDriver -l 0xc8000 0x00116f29

//问题代码的位置
-[RSUserMessageVC messageListAry] (in NetworkTaxiDriver) (RSUserMessageVC.m:54)
thinkjoytekiMacBook-Pro:NetworkTaxiDriver.app.dSYM thinkjoy$ 

注意:使用armv7arm64定位到的代码完全不同。

2.有模块地址,可以直接计算。
test 0x00000001018157dc 0x100064000 + 24844252

0x00000001018157dc代码地址,0x100064000模块地址;

你可能感兴趣的:(使用NSSetUncaughtExceptionHandler收集崩溃日志并分析)