为啥在 swift 中创建字符串时会出现内存泄漏?

Posted

技术标签:

【中文标题】为啥在 swift 中创建字符串时会出现内存泄漏?【英文标题】:Why is there a memory leak at String creation in swift?为什么在 swift 中创建字符串时会出现内存泄漏? 【发布时间】:2015-07-14 08:58:43 【问题描述】:

泄漏是Root Leak,在这张图片中,同一行发生了多次,但下面还有一个称为单次泄漏,也会产生泄漏。

这是调用栈之后调用前面所述的代码行。

这是 Instruments 定位泄漏的类:

class Item 
 var id: String!
 var name: String!

 internal init(name: String) 
    self.name = name
    self.id = name
 

 var description: String 
    return "(\(id)) \(name)"
 

在包含return "(\(id)) \(name)" 的计算变量description 行检测到泄漏,并将description 更改为:

var description: String 
    return "(" + id + ") " + name

更新:

var description: String 
    if let id = self.id as? String, let name = self.name as? String 
        return "(\(id)) \(name)"
    
    return "NO AVAILABLE DESCRIPTION"

最后一个发出“来自'String!'的条件转换! to String 总是成功”。

所以,即使这看起来像是一个 hack。

为什么会导致泄漏?

【问题讨论】:

很可能是这个类之外的东西导致了泄漏。检查创建此 Item 对象的类。它是引用 id 还是 name?另外,泄漏是一个“循环”吗?这也表明这个类之外的东西正在持有对它的引用。 @Stephen 我已经更新了问题,添加了一些关于泄漏的见解 两种形式的字符串连接都应该是有效的。看起来这可能是苹果的错误。您可以尝试向 Apple 提交错误报告。 【参考方案1】:

我测试了你的代码并经历了几个线程,我的理解是,当使用字符串插值而不是直接使用可选变量时,你必须可选绑定if let 子句。对于字符串连接,如果我们直接使用可选项是没有问题的。问题在于插值。

var description: String 
    if let id = self.id, let name = self.name 
        return "(\(id)) \(name)"
    
    return "NO AVAILABLE DESCRIPTION"

您可以在这里memory leak in Swift String interpolation 获得更多信息。 似乎是一个错误,可能会在未来的版本中得到解决。

【讨论】:

此内存泄漏,如果我使用多个可选变量,我会发生插值,其中一个效果很好。 我尝试了你的代码,即使我的班级变量 idnameString! 并且 Xcode 声明“来自'字符串的条件转换!' to String 总是成功”它编译并停止抛出这样的泄漏。 我在这里测试过,我也得到了同样的结果。 我将您的提示添加到主要问题中以获得更好的可见性,如果没有人可以给我一个更好的答案 “为什么?” 这正在发生,那么正确的答案将是分配给你。由于我会假设存在错误,遗憾的是我自己无法提交这样的错误报告。 如果你想检查它的状态,这里有一个类似问题的错误报告bugs.swift.org。

以上是关于为啥在 swift 中创建字符串时会出现内存泄漏?的主要内容,如果未能解决你的问题,请参考以下文章

仪器报告内存泄漏。不明白为啥

如何在 Java 中创建内存泄漏?

如何在 Java 中创建内存泄漏?

如何在 Java 中创建内存泄漏?

如何释放在子对话框中创建的 CWin 对象以避免内存泄漏

React 通用 redux-saga 内存泄漏