Swift中使用带unownedExecutor的GlobalActor触发EXC_BAD_ACCESS问题
自定义GlobalActor触发EXC_BAD_ACCESS错误的排查与修复
作为Swift新手,我尝试参照Apple文档实现一个基于unownedExecutor的最小化GlobalActor,让它在专用线程上运行。编写测试代码后,点击Test按钮时,在Task.detached语句处触发了EXC_BAD_ACCESS错误,对比网上示例没发现代码差异,请求排查原因。
原实现代码
GlobalActor实现
@globalActor actor BackendActor: GlobalActor { static let shared = BackendActor() nonisolated let unownedExecutor: UnownedSerialExecutor = Executor().asUnownedSerialExecutor() final private class Executor: SerialExecutor { private let dispatcher = DispatchQueue(label: "BackendQueue") internal func enqueue(_ job: UnownedJob) { self.dispatcher.async { job.runSynchronously(on: sharedUnownedExecutor) } } internal func asUnownedSerialExecutor() -> UnownedSerialExecutor { UnownedSerialExecutor(ordinary: self) } } }
测试代码
import SwiftUI @main struct TestApp: App { var body: some Scene { WindowGroup { ContentView() } } } struct ContentView: View { var body: some View { Button("Test") { Task.detached { @BackendActor in print("Ok") } } } }
错误原因
问题出在Executor实例的生命周期上:你直接在unownedExecutor的初始化语句中创建Executor()并转换为UnownedSerialExecutor,但**UnownedSerialExecutor对Executor实例的引用是无主(unowned)的**,没有强引用持有这个Executor对象。当初始化完成后,Executor实例会被立即释放,后续尝试访问它时就会触发EXC_BAD_ACCESS错误。
另外原代码中job.runSynchronously(on: sharedUnownedExecutor)存在未定义标识符的问题,这也是潜在的崩溃诱因。
修复方案
需要在BackendActor中添加一个强引用属性来持有Executor实例,确保它不会被提前释放,同时修正runSynchronously的参数。修改后的代码如下:
@globalActor actor BackendActor: GlobalActor { static let shared = BackendActor() // 强引用持有Executor实例,避免被提前释放 nonisolated private let executor = Executor() nonisolated let unownedExecutor: UnownedSerialExecutor init() { // 通过持有的executor创建UnownedSerialExecutor self.unownedExecutor = executor.asUnownedSerialExecutor() } final private class Executor: SerialExecutor { private let dispatcher = DispatchQueue(label: "BackendQueue") internal func enqueue(_ job: UnownedJob) { self.dispatcher.async { // 使用当前Executor的无主引用 job.runSynchronously(on: self.asUnownedSerialExecutor()) } } internal func asUnownedSerialExecutor() -> UnownedSerialExecutor { UnownedSerialExecutor(ordinary: self) } } }
内容的提问来源于stack exchange,提问作者kostrykin
相关产品推荐
相关产品推荐

