Xcode14.3/Swift5中数组索引越界崩溃异常排查求助
我正在开发一款访问结构体数组的App,使用Xcode 14.3/Swift 5环境。循环执行时出现崩溃,报错信息为:
Thread 142: Fatal error: Index out of range
对应代码行:
if serverConfig.serverURL == self.appDelegate.serverConfigurations[index].serverURL
但调试时获取到的信息显示:
(lldb) po self.appDelegate.serverConfigurations.count 5
(lldb) po index 2
按常理该索引不应触发越界崩溃,特此求助原因。
补充说明:serverConfigurations数组在AppDelegate的application(_:didFinishLaunchingWithOptions:)方法中构建,从UserDefaults读取字典数组并初始化ServerConfiguration实例,代码如下:
if let savedConfigurations = userDefaults.array(forKey: CONFIGURATION_KEY) { var index = 0; for item in savedConfigurations { let dictionaryConfig = item as! Dictionary<String, String> let serverConfig = ServerConfiguration.init(serverURL: String.init(dictionaryConfig[SERVER_URL_KEY]!) , regionName:String.init(dictionaryConfig[REGION_NAME_KEY]!), isRefreshing: false, index: index, networkFailures: 0, lowFPSWarnings: 0) serverConfigurations.append(serverConfig) index += 1 let serverStatus = ServerStatus.init(serverURL: dictionaryConfig[SERVER_URL_KEY], sim: nil, regionName: dictionaryConfig[REGION_NAME_KEY], fps: nil, timeDilation: nil, uniqueVisitors: nil, regionStatus: "Status: Unknown", restarts: nil, lastRestart: nil, lastUpdate: Date.distantFuture, statusUnknown: true, shownError: false) self.serverStatus.append(serverStatus) } }
多线程竞态条件:崩溃发生在Thread 142,说明代码在非主线程执行。Swift的
Array并非线程安全,若serverConfigurations同时被其他线程(比如主线程)执行删除、清空等修改操作,就会出现「调试时count为5,但访问瞬间数组长度已小于3」的矛盾情况。
解决:给serverConfigurations的读写操作添加线程锁(比如NSLock),或改用线程安全容器;也可确保所有对该数组的访问都在同一线程(如主线程)执行。调试时机延迟:你在lldb中打印
count和index时,崩溃已经发生,此时数组状态可能和崩溃瞬间不一致。比如崩溃时数组被修改为长度2,之后又被恢复为5,调试看到的是恢复后的状态。
解决:在崩溃代码行前添加日志,实时打印serverConfigurations.count和index的值;或添加条件断点:当index >= serverConfigurations.count时触发,捕获崩溃瞬间的真实状态。数组被意外修改:检查代码其他位置是否存在对
serverConfigurations的移除、重赋值操作,比如调用remove(at:)、removeAll(),或直接将数组赋值为空数组。这些操作可能在崩溃前瞬间执行。
解决:给serverConfigurations添加属性观察者didSet,当数组变化时打印日志和调用栈,追踪修改来源。强制解包的潜在风险:代码中大量使用
!强制解包(如dictionaryConfig[SERVER_URL_KEY]!),若UserDefaults数据格式有误,可能引发其他崩溃。虽当前崩溃指向索引越界,但仍建议替换为可选绑定,避免意外问题。
内容的提问来源于stack exchange,提问作者Nemesys Software

