在一个类中,我将所有成员读/写到串行dispatchQueue中,以保护多线程访问。但是,当我在deinit中将self
传递给dispatchQueue的任务时,出现了一个致命错误,该错误涉及对[unowned self]
的无主引用。
在下面的示例中,在调用self
之前,我仍然可以在refCount(self)
中读取deinit{}
,并且self.q.sync{...}
仍不为0。然后在将[unowned self]
传递到队列的任务
class Host {
let text = "Hello"
let q = DispatchQueue(label: "workingloop")
deinit {
// `self` is ok to be read
print("begin count: \(CFGetRetainCount(self)), ptr: \(Unmanaged.passUnretained(self).toOpaque())")
self.q.sync { [unowned self] in // <- callstack stop here
print(self.text)
}
// not reach
print("end count: \(CFGetRetainCount(self)), ptr: \(Unmanaged.passUnretained(self).toOpaque())")
}
}
func foo() {
let host = Host()
// <- trigger Host.deinit()
}
begin count: 2, ptr: 0x000000010871fb00
Fatal error: Attempted to read an unowned reference but object 0x10871fb00 was already deallocated 2020-01-13 10:31:11.758734+0800 xctest[29473:2710298] Fatal error: Attempted to read an unowned reference but object 0x10871fb00 was already deallocated
class.deinit{}
是否有特殊的作用域,我们不应该将self
传递给另一个线程或任务?
我也尝试使用[weak self]
通过,并且self
仍然是nil
。不知道为什么它的引用计数在另一项任务中达到零。
什么是是 deinit
?这是在释放引用类型实例时。 为什么被释放?因为它的引用计数达到0。这就是引用计数内存管理is。
不知道为什么在另一项任务中其引用计数达到零。
我不知道您的意思是“在另一项任务上”。根据定义,它的参考计数在deinit
中为零。