Swift 用 LET 定义的常量有时会在读取 (OSX) 时产生 EXC_BAD_ACCESS (EXC_I386_GPFLT)

Swift constant defined with LET sometimes produces EXC_BAD_ACCESS (EXC_I386_GPFLT) on read (OSX)

在我的 AppDelegate 中,我有一个状态栏图标常量,在应用程序繁忙时使用:

class AppDelegate: NSObject, NSApplicationDelegate {

let busyImage = NSImage(named: "BusyStatus");
...

在另一个 class 中,我在应用 运行 期间多次访问此应用。在配备 SSD 的 Macbook Air 上,我有时会收到

EXC_BAD_ACCESS (SIGSEGV)
Exception Codes:       EXC_I386_GPFLT

Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
0   libswiftCore.dylib              0x0000000103876cf9 swift_unknownRetain + 41
1   de.test.myapp   0x000000010304743b TestApp.AppDelegate.busyImage.getter : ObjectiveC.NSImage? (in TestApp) (AppDelegate.swift:0)
2   de.test.myapp   0x0000000102f9aa77 TestApp.Sync.(update (TestApp.Sync) -> () -> ()).(closure #2) (in TestApp) (Sync.swift:271)

那里的代码:

statusBarItem!.image = appDelegate!.busyImage

它在主线程中调用的块中:

let updateBlock: () -> () = {

    appDelegate!.statusBarItem!.image = self.appDelegate!.busyImage
        [... other code ...]
 }

 if NSThread.isMainThread()
 {
     updateBlock()
 }
 else
 {
     dispatch_sync(dispatch_get_main_queue(),updateBlock)
 }

什么会导致这种情况以及如何避免这种情况?

自从 swift 2 之后,问题似乎就消失了。 再也没有遇到过这个问题,我的代码也没有任何改变。

各位网友,大家好,

我的环境是 macOS 10.15.4,我是 运行 XCode 11.5 (11E608c) 和 Swift 5.

我这里有一小段代码有完全相同的问题,在使用旋转时 100% 的时间都失败了:

override func rotate(delta: float2) {
    let sensitivity: Float = 0.005
    rotation.y += delta.x * sensitivity    // FAILS with Thread 1: EXC_BAD_ACCESS (code=EXC_I386_GPFLT)
    _viewMatrix = updateViewMatrix()
}

这段代码看起来一点也不奇怪。 rotation 是在 Class 中定义的浮点向量:

var rotation: float3 = [0, 0, 0]

现在,我花了一些时间尝试同一函数的多个版本,如果我将其重写为:

override func rotate(delta: float2) {
    let sensitivity: Float = 0.005
    var deltaX: Float = delta.x * sensitivity
    rotation.y += deltaX
    _viewMatrix = updateViewMatrix()
}

它现在运行顺利。这太疯狂了,因为我看不出明显的原因。我不尝试更改常量,甚至 linter 建议我将 deltaX 定义中的 var 更改为 let

我觉得这是一个 Swift 问题,但这对于许多人使用的语言的第 5 版来说令人担忧。

如果我找到解决方案或至少找到有效的解释,我会更新我的答案。

小伙子们长命百岁!