存储弱引用有时会导致内存泄漏。

12

我有一个名为 class A 的类,它存储了一个指向其他对象的 可选弱引用变量,该对象是 A 的子类。有时候当我将一些内容存储到这个变量中时会出现 内存泄漏 - 这种情况很少发生,但确实存在。我在 forEach 循环中 分配此变量,但我也在应用程序的其他地方使用 weak var 时发现了类似的内存泄漏问题,因此我不认为循环与此有任何关系。 负责此问题的库是 libswiftCore.dylib,负责帧是 swift::RefCounts<swift::RefCountBitsT<(swift::RefCountInlinedness)1> >::formWeakReference()。是否有其他人遇到过类似的问题?有没有办法解决这个问题?

进入图像描述

进入图像描述

进入图像描述


从未见过这种情况,但对于苹果框架中的泄漏问题,您应该提交错误报告。 - Nima Yousefi
我有一个问题。我认为这是一个Swift的问题,但我不知道为什么它会在某些特定情况下发生。我能够通过使用Unmanaged<T>来解决它,但决定放弃修复以获得更可读的代码。顺便说一下,在我的情况下,我存储在弱属性中的实际对象没有被保留,所以不修复这个问题对我来说是可以的。 - Binary Pulsar
你能提供一个最小可行的代码片段来重现问题吗?请剥离掉与泄漏有关的无关内容。 - Kamil.S
1个回答

5
尝试将变量设置为unowned,而不是weak。这算是Swift的一个错误,因为开发人员在捕获嵌套闭包的强引用时没有警告,但目前将其设置为unowned应该可以作为解决方法。
编辑1:https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20151207/001197.html 提到了从这里进行改进:
class ViewControllerBase: UIViewController {
let timer:DispatchSourceTimer = DispatchSource.makeTimerSource(flags: [], queue:  DispatchQueue(label: "q.q"))

deinit {
    NSLog("deinit of \(NSStringFromClass(type(of: self)))")
}

override func viewDidLoad() {
    super.viewDidLoad()

    timer.scheduleRepeating(deadline: .now(), interval: .seconds(1))

    timer.setEventHandler {
        UIView.animate(withDuration: 0.2) { [weak self] in
            self?.view.backgroundColor = UIColor.green
        }
    }
}

这种情况下存在一种微妙的内存泄漏...即使self只以"weak"方式使用,也存在保留循环。这是因为嵌套的闭包捕获了强引用,以便在接下来的闭包中使用。
编辑2: 我可能错了,但OP正在使用changes.forEach闭包,然后又使用changes.added.forEach闭包。我可能错了,但这可能是整个问题的原因,也许在那里声明[weak self] (cluster, change)可以可能消除这个问题。这是Swift的内置闭包,但仍然是一个闭包,可能会导致它们被嵌套。
尝试将您的代码更改为:
changes.forEach{[weak self] (cluster, change) in

看看那是否有帮助

或者

changes.forEach{[unowned self] (cluster, change) in

您能否复制您的代码,而不是截图,因为这样更容易重新创建您的代码,而不必重新输入它。


"unowned"和"weak"有不同的含义-"weak"在定义上是可选的,必须在使用之前解包(无论是否安全),我们可以安全地检查它是否为nil(因为它是可选的)。 "unowned"不能是可选的,因此在需要使用“weak”(并检查为nil)的情况下不适用。至于“这是错误”,您能引用任何权威来源吗? - Fyodor Volchyok
1
尽管您提供的信息非常有用(在我看来),并且让我思考了很多问题,但它只涉及两个嵌套闭包的一个特定情况。我没有这样的代码,我只有weak var(就像问题作者一样),但它仍然会产生泄漏。 - Fyodor Volchyok
制作最小可重现示例需要一些时间,可能还需要在SO上提出另一个问题。我希望能够快速解决这个问题。如果几天内没有看到其他答案,我会自己制作示例。 - Fyodor Volchyok
我的错,从问题作者提供的代码来看,可能是这种情况。让我们等待他的反馈。 - Fyodor Volchyok
你能同时发布带有注释的代码部分,以便我们查找内存循环的问题吗? - AD Progress
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接