__NSDictionaryM执行dealloc时崩溃,cow_cleanup作用及崩溃诱因技术问询
cow_cleanup 函数作用
cow 是写时复制(Copy-on-Write)的缩写,cow_cleanup 是 CoreFoundation 中可变集合类(你崩溃栈里的 __NSDictionaryM 就是系统可变字典的内部类)释放流程的专属函数,核心职责是处理可变集合基于写时复制机制分配的底层内存资源:
- 当可变字典是从不可变 NSDictionary 拷贝生成时,底层会先复用原不可变字典的内存空间,只有首次对可变字典执行增删改操作时,才会拷贝数据开辟独立内存,这就是写时复制的优化逻辑
cow_cleanup会在可变字典销毁时,判断底层内存是否和其他对象共享、是否需要单独释放、调整对应的引用计数,同时遍历释放字典中存储的所有 key 和 value 对象
你崩溃在 objc_release + 16 位置,说明 cow_cleanup 遍历释放字典内元素的时候,访问到了已经被提前释放的野指针地址。
崩溃诱因判断
你猜测的「Model 释放过程中 NSDictionary 被修改」是高概率诱因,除此之外还有两种常见的同因变种:
- 多线程读写冲突:这个可变字典同时被多个线程操作,0号线程正在走释放流程,其他线程同时在修改字典的结构(增删 key/value),导致
cow_cleanup遍历时底层存储的元素列表已经被篡改,访问到非法地址 - 字典内存储的对象提前悬垂:存入这个字典的某个元素已经在其他线程被释放,引用计数归零,
cow_cleanup尝试二次释放这个对象触发崩溃
快速排查方案
- 先确认属性修饰符:如果该属性是 NSMutableDictionary 类型,不能用
copy修饰,必须用strong修饰。用copy修饰可变集合赋值时会生成不可变实例,后续强转为可变修改会直接触发异常 - 统一线程保护:所有对这个字典的读写操作都放到同一个串行队列,或者加同一把互斥锁,禁止多线程无保护同时读写
- 开启 Zombie 调试:Xcode scheme 中开启 Zombie Objects 后复现崩溃,会直接打印出被提前释放的对象类型,快速定位根因
内容的提问来源于stack exchange,提问作者SFly
相关产品推荐
相关产品推荐

