一次惨重的崩溃教训 swizzleMethod不可滥用

##前言 最近项目有几个因为NSDictionary的value或者key是nil导致崩溃的bug,虽然不多,但是检查起来却有些麻烦,为了省事,直接把系统的几个方法替换成了自己的方法。 举个栗子:NSMutableDictionary:

Class class = NSClassFromString(@"__NSDictionaryM");
[class mhs_swizzleMethod:@selector(setObject:forKey:) withMethod:@selector(gl_setObject:forKey:)];
[class mhs_swizzleMethod:@selector(setObject:forKeyedSubscript:) withMethod:@selector(gl_setObject:forKeyedSubscript:)];

复制代码

实现:

- (void)mhs_setObject:(id)anObject forKey:(id<NSCopying>)aKey {
    if (!aKey) {//没有key直接returnreturn;
    }
    if (!anObject) {//没有value则赋一个NSNull对象
        anObject = [NSNull null];
    }
    [self mhs_setObject:anObject forKey:aKey];
}

- (void)mhs_setObject:(id)obj forKeyedSubscript:(id<NSCopying>)key {
    if (!key) {
        return;
    }
    if (!obj) {//打印一下,用于测试
#if defined(DEBUG)||defined(_DEBUG)
        NSLog(@"有空值setObject:forKeyedSubscript: key=%@",key);
#endif
        obj = [NSNull null];
    }
    [self mhs_setObject:obj forKeyedSubscript:key];
}
复制代码

结果发现,会打印很多,诸如:

这些主要是引入了 GrowingIO,打印的字典键值。

反正也没崩溃什么的,就没有放在心上。


##继续 更新版本后,突然涌现大量崩溃,不知为何,友盟统计都是这种崩溃日志: Application received signal SIGSEGV Application received signal SIGBUS SIGSEGV和SIGBUS一般是因为访问已被释放的内存或者调用不存在的方法导致的,但是没有具体信息。回想了一下更新版本我所做的修改,一个是swizzleMethod,一个是应用里数据库的一些优化,想来想去,也就只有这里可能有问题。而且基本上崩溃都是应用进入后台再唤醒进入前台后发生。(重要信息)


##但是

我大量测试应用发生崩溃的条件发现崩溃看起来好像跟swizzleMethod没有关系。

发现元凶都是极光推送的一个线程坏指针异常。 到底是怎么回事? 再次看看打印日志,应用启动,极光SDK启动。

当应用进入后台超过三分钟,融云,极光均断开连接,打开应用,融云,极光重新连接,融云连接成功: [RongCloud][L-connect-R], result: success, type: sdk_retry 点击应用任意界面,崩溃。 极光最后打印: | JIGUANG | E - [JIGUANGSessionController] ack timeout for request rid: 147 于是我把swizzle的方法全部注释,再尝试,极光没有崩溃,重连成功。反复尝试,结果都一致。结论证实。 打印如下: 2017-03-23 23:38:14.912956 MiHuaShi[13827:5611206] | JIGUANG | I - [JIGUANGSessionController] connecting with coreAddr 121.46.20.40,port 7003 2017-03-23 23:38:15.037784 MiHuaShi[13827:5611206] | JIGUANG | I - [JIGUANGLogin] ----- login result ----- uid:88********** registrationID:121*****************

##结论 swizzle系统方法不可滥用,首先系统如何实现没有开源谁都不知道,任意更改谁也不敢保证一定安全,应该在平时细心注意,避免出现低级错误而非投机取巧运用黑魔法。 虽然我不知道极光SDK经历了什么,我也不知道为什么会导致崩溃,但是事实确实如此,幸亏崩溃发生条件比较明显,那就是从后台进入前台,要不然我真会浪费更多的精力在这上面。

转载于:https://juejin.im/post/5a3218735188253d681799a9

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值