iOS objc_msgSend 野指针Crash 从 Log 提取 Crash 时 selector 的地址和名字并打印

从 crash stack log 里面,提取 objc_msgSend 关键字,定位是否是野指针问题导致的crash,如果是则打印 crash 时的 objc_msgSend 调用的第二个参数,即 selector 的地址和名字String,方便定位和 fix 此类型的 crash。

具体提取方法:
1. 提取字符串地址:
32bit 机器,读取 crash 时 log 里面 r1: 0x 后面的 8 个 16 进制数字字符串;
64bit 机器,读取 crash 时 log 里面 x1: 0x 后面的 16 个 16 进制数字字符串;
2. 通过 strtoul 将字符串地址转化为无符号整型地址;
3. 同时打印 selector 的 “地址” 和 selector “字符串” 即 selectorName。

static void printLastSelectorName(NSString *crashStackString)
{
    // print registers
    QZLOG_INFO(@"*** print registers begin. ***");
    
    if (crashStackString.length > 0 && ([crashStackString rangeOfString:@"objc_msgSend"].location != NSNotFound)) {
        
        QZLOG_INFO(@"*** have found objc_msgSend. ***");
        
        NSString *r1Flag = @"r1: 0x";
        NSString *x1Flag = @"x1: 0x";
        NSRange rangeContainsR1Reg = [crashStackString rangeOfString:r1Flag];
        NSRange rangeContainsX1Reg = [crashStackString rangeOfString:x1Flag];
        
        NSString *valOfR1X1 = nil;
        
        @try {
            if ((rangeContainsR1Reg.location != NSNotFound) && (crashStackString.length >= rangeContainsR1Reg.location + r1Flag.length + 8)) { // 32-bit
                valOfR1X1 = [crashStackString substringWithRange:NSMakeRange(rangeContainsR1Reg.location + r1Flag.length, 8)];
            }
            else if ((rangeContainsX1Reg.location != NSNotFound) && (crashStackString.length >= rangeContainsX1Reg.location + x1Flag.length + 16)) { // 64-bit
                valOfR1X1 = [crashStackString substringWithRange:NSMakeRange(rangeContainsX1Reg.location + x1Flag.length, 16)];
            }
        }
        @catch (NSException *exception) {
            QZLOG_ERROR(@"*** exception: %@", exception);
        }
        
        if (valOfR1X1.length > 0) {
            unsigned long val = strtoul([[valOfR1X1 substringWithRange:NSMakeRange(0, valOfR1X1.length)] UTF8String], 0, 16);
            if (val != 0 && val != ULONG_MAX) {
                
                QZLOG_INFO(@"*** r1(x1) val = %lx", val);
                QZLOG_INFO(@"*** r1(x1): %@", NSStringFromSelector((SEL)val));
            }
        }
    }
    
    QZLOG_INFO(@"*** print registers end. ***");
}


posted on 2016-06-14 18:41  封起De日子  阅读(196)  评论(0编辑  收藏  举报

导航