使用DoraemonKit时NSLog触发Bus error:10崩溃的原因与解决方法
问题分析与解决方案
问题成因
从崩溃堆栈和异常信息来看,崩溃由DoraemonKit的NSDictionary分类方法触发:
- DoraemonKit重写了
NSDictionary的descriptionWithLocale:indent:方法(对应堆栈第6帧),该方法内部会尝试将字典序列化为JSON格式字符串,实现Unicode可读的日志输出。 - 你的
receivedDic(通知的userInfo)存在以下一种或多种问题:- 包含不可JSON序列化的对象(比如自定义对象、非Foundation标准类型,或存在循环引用的对象);
- 字典本身是野指针,或字典内的部分对象已被提前释放;
- JSON序列化过程中触发内存访问错误(SIGBUS总线错误通常对应未对齐内存访问或非法内存地址,此处堆栈显示在malloc阶段,说明序列化时内存分配或访问出现异常);
- DoraemonKit的该分类方法未对JSON序列化的异常做捕获处理,直接导致崩溃。
解决方法
临时应急方案
- 线上版本完全移除DoraemonKit:调试工具不应出现在正式发布的App中,这是开发规范,也是避免此类调试相关崩溃的根本手段;
- Debug环境下,关闭DoraemonKit的Unicode日志格式化功能(可在DoraemonKit的设置面板中找到对应开关)。
根本修复方案
检查通知的userInfo内容:
确保发送通知时传递的userInfo仅包含可JSON序列化的Foundation对象(NSString、NSNumber、NSArray、NSDictionary、NSNull),且无循环引用。如果需要传递自定义对象,应先转为JSON兼容格式(比如转成字典),避免直接放入userInfo。修复DoraemonKit的分类方法:
给-[NSDictionary(DoraemonUnicodeReadable) descriptionWithLocale:indent:]添加异常捕获,当JSON序列化失败时,回退到父类的默认实现:- (NSString *)descriptionWithLocale:(id)locale indent:(NSUInteger)indent { @try { NSData *jsonData = [NSJSONSerialization dataWithJSONObject:self options:NSJSONWritingPrettyPrinted error:nil]; if (jsonData) { return [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding]; } } @catch (NSException *exception) { // 序列化失败时调用父类方法 } return [super descriptionWithLocale:locale indent:indent]; }确保对象内存安全:
检查通知发送方是否正确持有userInfo字典,避免在通知回调前提前释放字典或其中的对象,导致回调时访问野指针。升级DoraemonKit:
尝试升级到DoraemonKit的最新稳定版本,官方可能已经修复了该异常未捕获的问题。
内容的提问来源于stack exchange,提问作者Tolgay Toklar
相关产品推荐
相关产品推荐

