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:@"%@<br>\niOS_Version : %@----PhoneSize : %@<br>\n----iPhoneType: %@<br>\nApp_Version : %@<br>\nuserID : %@<br>\nuserName : %@<br>\nname:%@<br>\nreason:\n%@<br>\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<br>
reason:
*** -[__NSPlaceholderDictionary initWithObjects:forKeys:count:]: attempt to insert nil object from objects[0]<br>
callStackSymbols:
0   CoreFoundation                      0x2141a303 <redacted> + 150
1   libobjc.A.dylib                     0x20be6dff objc_exception_throw + 38
2   CoreFoundation                      0x21337e2b <redacted> + 342
3   CoreFoundation                      0x21337caf <redacted> + 50
4   NetworkTaxiDriver                   0x0012ff29 NetworkTaxiDriver + 323369
5   NetworkTaxiDriver                   0x0013019f NetworkTaxiDriver + 323999
6   UIKit                               0x25695d29 <redacted> + 2976
7   UIKit                               0x2569507b <redacted> + 378
8   UIKit                               0x2569c995 <redacted> + 328
9   UIKit                               0x25735f45 <redacted> + 488
10  NetworkTaxiDriver                   0x0013013b NetworkTaxiDriver + 323899
11  UIKit                               0x255b1d79 <redacted> + 1028
12  UIKit                               0x255b1959 <redacted> + 24
13  UIKit                               0x2566f4d5 <redacted> + 280
14  UIKit                               0x2566e8e5 <redacted> + 96
15  UIKit                               0x2566e51b <redacted> + 834
16  UIKit                               0x2566e16d <redacted> + 52
17  UIKit                               0x2566e0e7 <redacted> + 214
18  UIKit                               0x255ada83 <redacted> + 714
19  QuartzCore                          0x23689ad5 <redacted> + 128
20  QuartzCore                          0x236851d1 <redacted> + 352
21  QuartzCore                          0x23685061 <redacted> + 16
22  QuartzCore                          0x23684581 <redacted> + 368
23  QuartzCore                          0x23684233 <redacted> + 614
24  UIKit                               0x255b08d7 <redacted> + 5518
25  CoreFoundation                      0x213dd257 <redacted> + 14
26  CoreFoundation                      0x213dce47 <redacted> + 454
27  CoreFoundation                      0x213db1af <redacted> + 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 <redacted> + 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模块地址;


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值