iOS应用偶发EXC_BAD_ACCESS崩溃:访问Dictionary时异常求助
偶发EXC_BAD_ACCESS崩溃原因分析:Swift Dictionary访问问题
核心原因
- Swift字典并非线程安全:你提到多线程访问时未崩溃,但线程不安全的操作具有偶发性——只有当多个线程同时对字典执行读写、修改(包括
removeAll)操作时,才会破坏字典内部存储结构,导致后续访问触发内存错误。比如一个线程在遍历字典条目,另一个线程执行removeAll,或者读写操作并行发生,线程调度的不确定性直接导致崩溃偶发。 removeAll的并发风险:执行removeAll时,字典会重置内部存储结构,如果此时有其他线程正在访问字典的某个条目,就会出现访问已失效内存地址的情况,进而触发EXC_BAD_ACCESS。
验证说明
你认为多线程访问未崩溃,只是因为线程竞争的触发条件苛刻——只有当两个线程的操作刚好在字典内部结构变更的临界区重叠时,才会出现崩溃,大部分情况下线程调度不会刚好命中这个临界区,所以表现为偶发。
解决方案
给字典的所有操作添加线程同步机制,确保同一时间只有一个线程访问字典,示例如下:
方案1:使用串行队列
static let whiteLabelQueue = DispatchQueue(label: "com.yourapp.whitelabel.queue") static var whiteLabelling = [String : String]() // 读取操作 static func getWhiteLabelValue(forKey key: String) -> String? { var value: String? whiteLabelQueue.sync { value = whiteLabelling[key] } return value } // 设置操作 static func setWhiteLabelValue(_ value: String, forKey key: String) { whiteLabelQueue.async { whiteLabelling[key] = value } } // 清空操作 static func clearWhiteLabelling() { whiteLabelQueue.async { whiteLabelling.removeAll() } }
方案2:使用NSLock
static let whiteLabelLock = NSLock() static var whiteLabelling = [String : String]() // 读取操作 static func getWhiteLabelValue(forKey key: String) -> String? { whiteLabelLock.lock() defer { whiteLabelLock.unlock() } return whiteLabelling[key] } // 设置操作 static func setWhiteLabelValue(_ value: String, forKey key: String) { whiteLabelLock.lock() defer { whiteLabelLock.unlock() } whiteLabelling[key] = value } // 清空操作 static func clearWhiteLabelling() { whiteLabelLock.lock() defer { whiteLabelLock.unlock() } whiteLabelling.removeAll() }
内容的提问来源于stack exchange,提问作者michaelsmith
相关产品推荐
相关产品推荐

