【问题标题】:Strong, weak references + Mirror: causing leak强、弱引用 + 镜像:导致泄漏
【发布时间】:2019-01-09 06:28:35
【问题描述】:

下面的Parent 类对单个子对象具有强引用和弱引用。子对象永远不会被释放。删除弱引用并释放孩子。

调用Mirror 方法是造成这种泄漏的必要条件,但我不明白为什么使用镜像会导致这种行为。不保留镜像的结果。

对于弱引用和强引用,只有父 deinit 被执行!

Parent deinit

我希望看到父对象和子对象都被释放,因此日志显示:

Parent deinit
DeinitLogger deinit

删除弱引用,日志显示两个对象 deinit,如预期的那样。

你能帮我理解为什么会泄漏吗? (这不是游乐场,而是在应用程序中)。

class DeinitLogger {
    deinit {
        print("DeinitLogger \(#function)")
    }
}

class Parent: NSObject {

    weak var weakLogger: DeinitLogger?
    var strongLogger: DeinitLogger

    override init() {

        let logger = DeinitLogger()

        // Create a weak ref
        weakLogger = logger  // comment out this line, no leak!

        // Create a strong ref to same object.
        strongLogger = logger

        super.init()

        // Invoking mirror and adding the properties to a dict leaks when one of the
        // properties is weak.
        let dict = dictionaryOfProps()
        print(dict)
    }

    deinit {
        print("Parent \(#function)")
    }

    /// Generates a dictionary of property names -> properties
    /// e.g. "strongLogger" -> type of strongLogger.
    private func dictionaryOfProps() -> [String: Any] {
        var result = [String: Any]()
        let mirror = Mirror(reflecting: self)
        for case let(label?, value) in mirror.children {
            result[label] = value
        }
        return result
    }
}

// Chuck these two lines in a viewDidLoad(), or anywhere. 
var o: Parent? = Parent()
o = nil // everything should be freed here.

【问题讨论】:

  • 我在一个应用程序中发现了这个问题,并将其归结为一个操场。但是,当然,将此代码翻译回 App 并且它确实可以正常工作。啊!回到沸腾状态。谢谢。
  • 好吧...我回到应用程序并更改了我的煮沸食谱。现在有一个Mirror 参与其中。弱 ref + mirror 甚至在应用程序中也会导致泄漏!
  • 我可以重现这个问题,但我承认我不知道这里发生了什么。 – 代替 let dict = dictionaryOfProps(); print(dict) 在 Parent.init 方法中执行 for _ in Mirror(reflecting: self).children { } 就足够了。
  • 是的,必须包含children 的一些迭代。谢谢你检查我的眼睛。这并不明显,是吗。我想我会针对 Swift 打开一个错误。
  • bugs.swift.org/browse/SR-8878,已经在开发分支中修复了。

标签: swift


【解决方案1】:

这是 Swift 4.2 (Xcode 10) 中的一个已知错误:

在读取ReflectionMirror.m 中的弱引用时缺少版本导致。该错误已在 master 分支上修复。您的程序在 https://swift.org/download/#releases 的当前“Trunk Development (master)”快照中运行正常。

【讨论】:

  • 优秀。感谢您完成这项研究,Martin。
猜你喜欢
  • 2018-12-22
  • 1970-01-01
  • 1970-01-01
  • 2023-04-09
  • 2010-10-30
  • 2010-09-28
  • 1970-01-01
  • 2011-07-07
  • 1970-01-01
相关资源
最近更新 更多