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

Xcode中Swift多线程操作Class3遇EXC_BAD_ACCESS等错误求助

问题排查思路:Class3集合操作中的随机线程错误

背景概述

在Xcode Swift项目中:

  • Class3是仅包含变量的类,包含SOK、SO、SO2、SO3等集合类型变量
  • Class2含@Published变量及后台计算函数,最终会在主线程将Class3的变量同步到自身@Published变量更新UI
  • Class1作为调度类,通过串行OperationQueue和信号量调度Class2的127个操作

其中Class2的func_with_error函数(对应Class1的operation45)会随机触发两类错误:

  • Thread "X": EXC_BAD_ACCESS (code=1, address=0x18)(线程号不固定)
  • Thread "X": "-[NSTaggedPointerString objectForKey:]: unrecognized selector sent to instance 0x8000000000000000"

错误集中在if class3.SOK[i] != nil或append(class3.SOK[i]!)代码行。


排查方向

1. 强制保障集合的线程安全性

Swift的Array、Dictionary等基础集合本身不是线程安全的,即便你认为操作是串行的,也可能存在未监控到的跨线程读写:

  • 给Class3的所有集合操作添加线程锁,用NSLock或os_unfair_lock包裹读写逻辑,示例:
    class Class3 {
        private let lock = NSLock()
        var SOK: [Int: String] = [:]
        var SO: [String] = []
        var SO2: [String] = []
        var SO3: [String] = []
        
        // 安全读取SOK值
        func safeSOKValue(at index: Int) -> String? {
            lock.lock()
            defer { lock.unlock() }
            return SOK[index]
        }
        
        // 安全向SO添加元素
        func safeAppendToSO(_ value: String) {
            lock.lock()
            defer { lock.unlock() }
            SO.append(value)
        }
        
        // 安全检查SO2是否包含指定值
        func safeContainsInSO2(_ value: String) -> Bool {
            lock.lock()
            defer { lock.unlock() }
            return SO2.contains(value)
        }
        
        // 同理给SO3添加安全检查方法
    }
    
    替换func_with_error中的直接集合访问为这些安全方法,验证错误是否消失。

2. 修复变量捕获的潜在风险

period变量在func_with_error外层定义,被内部BlockOperation闭包捕获,可能导致意外的内存访问:

  • 将period移到operation1闭包内部,避免跨闭包共享变量,并补充默认分支处理未匹配的time值:
    let operation1 = BlockOperation {
        let period: Int
        switch time {
        case "1min", "5min", "15min", "30min", "1h", "2h", "4h", "1day":
            period = 450
        case "1month", "1week":
            period = 48
        default:
            period = 0 // 避免未匹配时period为0导致异常循环
        }
        // 后续循环逻辑使用此内部period变量
    }
    

3. 验证SOK的类型与索引合法性

错误-[NSTaggedPointerString objectForKey:]说明存在类型混淆问题:

  • 在Class3中显式指定SOK的类型,比如var SOK: [Int: String] = [:],避免类型推断错误
  • 检查所有修改SOK的代码,确保没有将非字典类型的值赋值给它
  • 确认循环中的i值范围是否在SOK的键集合内,即便有nil判断,也要防范遍历过程中字典被修改导致的索引异常

4. 排查内存释放问题

class3在appeallingFunctions_fromClass2外层定义,被后台闭包捕获,可能提前释放导致野指针:

  • 在Class1中添加属性持有class3,确保其生命周期覆盖所有后台操作
  • 开启Xcode的Zombie Objects工具,追踪已释放对象的访问,定位是否存在野指针问题

5. 简化代码定位问题

  • 暂时注释func_with_error中重复的判断逻辑(两次SO2.contains、两次SO3.contains),简化后验证错误是否还出现
  • 将OperationQueue替换为串行DispatchQueue的直接调用,排除BlockOperation依赖调度的潜在问题:
    DispatchQueue(label: "com.yourapp.serial").async {
        // 直接执行原operation1的逻辑
        // 完成后调用semaphore.signal()
    }
    

内容的提问来源于stack exchange,提问作者Micsa Dan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 02:21:04