iOS Swift应用swift_bridgeObjectRetain相关随机EXC_BAD_ACCESS崩溃求排查
Swift 异步闭包野指针崩溃排查方案
该崩溃属于Swift运行时对象内存管理异常,触发原因为已释放的对象被后台线程的异步闭包尝试持有,从崩溃日志的EXC_BAD_ACCESS错误、swift_retain调用栈可以确认不属于强制解包、try!触发的异常。
排查思路
- 精确符号化定位代码行:使用打包对应版本的dSYM文件,对崩溃地址
0x0000000102b59734做符号化,直接定位到DiscussionViewController.fetchPostData()闭包内的具体代码行,无需全量排查方法代码。可使用如下命令完成符号化:
其中atos -arch arm64 -o <你的APPNAME.app.dSYM/Contents/Resources/DWARF/APPNAME> -l 0x102a7c000 0x0000000102b597340x102a7c000为崩溃日志中给出的程序加载起始地址。 - 开启内存调试工具复现问题:本地调试时开启Xcode的Zombie Objects、Malloc Stack、Address Sanitizer调试选项,模拟快速进出
DiscussionViewController页面同时触发网络请求,大概率可以复现野指针问题。 - 检查闭包捕获的对象引用:虽然你已经对
self加了[weak self]修饰,但需要检查闭包内是否直接捕获了方法内的局部对象、控制器的成员属性、其他代理/回调对象,这些对象如果在主线程被提前释放,后台闭包访问时就会触发该崩溃。 - 排查并发访问问题:检查闭包内是否存在访问非线程安全的模型、数组等对象的逻辑,如果对象同时在其他线程被修改释放,也会触发引用计数操作异常。
解决方案
- 闭包内所有非全局对象优先通过
self?.xxx的方式访问,避免直接捕获外部对象,必须直接捕获的对象需要添加weak修饰。 - 将网络回调闭包内所有UI操作、成员属性修改逻辑统一派发到主线程执行,避免后台线程和主线程同时访问修改同一对象导致的内存异常。
- 若暂时无法复现问题,可以在
fetchPostData()的闭包内逐段添加业务埋点,通过用户崩溃前上报的最后一个埋点缩小问题代码范围。 - 确认存在多线程并发访问的对象时,添加串行队列锁保证访问线程安全。
内容的提问来源于stack exchange,提问作者sudoExclamationExclamation
相关产品推荐
相关产品推荐

