简体   繁体   English

在 deinit 中调用 dispatchQueue.sync 会导致 self 的无主引用

[英]Calling dispatchQueue.sync in deinit causes unowned reference of self

In a class, I put all members read/write in a serial dispatchQueue to protect multi-thread access.在一个类中,我将所有成员读/写在串行 dispatchQueue 中以保护多线程访问。 But I got a fatal error of unowned reference to self when I pass [unowned self] to dispatchQueue's task in deinit.但是当我在 deinit 中将 [unowned [unowned self]传递给 dispatchQueue 的任务时,我遇到了对self的 unowned 引用的致命错误。

In the following example, I can still read self and refCount(self) is still not 0 in deinit{} before calling self.q.sync{...} .在下面的示例中,在调用self.q.sync{...}之前,我仍然可以读取self并且refCount(self)deinit{}仍然不是 0。 Then fatal error raised immediately when passing [unowned self] to queue's task然后在将[unowned self]传递给队列的任务时立即引发致命错误

Example例子

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()
}

Output输出

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

Is the class.deinit{} a special scope where we should not pass self to another thread or task? class.deinit{}是一个特殊的范围,我们不应该将self传递给另一个线程或任务吗?

I also try to pass using [weak self] , and the self is still a nil .我也尝试使用[weak self]传递,而self仍然是nil Don't know why its reference count reached zero at another task.不知道为什么它的引用计数在另一个任务中达到零。

What is deinit ?什么是去deinit It is when a reference type instance is being deallocated.这是在释放引用类型实例时。 Why is it being deallocated?为什么会被解除分配? Because its reference count reached 0. That is what reference count memory management is .由于它的引用计数达到0,即引用计数的内存管理什么。

Don't know why its reference count reached zero at another task.不知道为什么它的引用计数在另一个任务中达到零。

I don't know what you mean by "at another task".我不知道您所说的“在另一项任务中”是什么意思。 Its reference count is zero in deinit by definition.根据定义,它的引用计数在deinit为零。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM