You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 23:55:15