从`deinit`中走私`self`

Ale*_*ica 6 memory-management non-deterministic automatic-ref-counting swift

如果我通过将其分配给一些外部强引用而走私self了我会发生什么deinit?下面的代码显然格式不正确:

class C: CustomStringConvertible {
    let s = "abc"

    var description: String {
        return "C(id: \(ObjectIdentifier(self)), s: \(s))"
    }

    deinit {
        print("deinit")
        globalObject = self
    }
}

var globalObject: C!

do {
    let localObject = C()
    print("localObject: \(localObject)")
    print("end of `do`")
}

print("globalObject: \(globalObject!)")
Run Code Online (Sandbox Code Playgroud)

您不能仅仅从a的中间“改变主意”来取消对象的初始化deinit。但有趣的是,此代码是不确定的,有时偶尔会成功完成,并打印:

localObject: C(id: ObjectIdentifier(0x00007f9063f00960), s: abc)
end of `do`
deinit
globalObject: C(id: ObjectIdentifier(0x00007f9063f00960), s: abc)
Run Code Online (Sandbox Code Playgroud)

我正在使用Code Runner运行此程序,后者仅使用运行单个文件Swift脚本swiftc。因此,这里没有任何Playground拥有的意外参考。

不确定性从何而来?

And*_*jen 0

这不是一个答案,但对于评论来说太长了:

有趣的是,我刚刚附加:

for _ in 1...1000000 {
    print("intermediate: \(globalObject!)")
}
print("globalObject: \(globalObject!)")
Run Code Online (Sandbox Code Playgroud)

进而:

swiftc test.swift
for ((i = 0; i < 10000; i++)); do
    ./test  | fgrep globalObject
done
Run Code Online (Sandbox Code Playgroud)

我得到的是(这 10000 次运行中只有一次):

致命错误:对象保留次数过多a(44854,0x10a92f5c0) malloc:已释放对象的校验和不正确0x7fcc1ec02b98:可能在释放后进行了修改。

损坏值:0x7ffffffe00000000

test(44854,0x10a92f5c0) malloc: *** 在 malloc_error_break 中设置断点进行调试

全局对象:C(id:对象标识符(0x00007f7f452006c0),s:abc)

test(61212,0x114d7e5c0) malloc:已释放对象 0x7fe063e00008 的校验和不正确:可能在释放后进行了修改。

损坏值:0x4ffffffe00000000

test(61212,0x114d7e5c0) malloc: *** 在 malloc_error_break 中设置断点进行调试

下次运行:

测试(7016,0x10682d5c0)malloc:tiny_free_list_remove_ptr:内部不变性损坏(上一个的下一个指针):ptr = 0x7fb2e0805fd0,prev_next = 0x7f92e0805fd0

这似乎是一些竞争条件,但我不知道谁在这里生成线程。顺便提一句:

swiftc -version
Apple Swift version 5.0.1 (swiftlang-1001.0.82.4 clang-1001.0.46.5)
Target: x86_64-apple-darwin18.7.0
Run Code Online (Sandbox Code Playgroud)