为啥在 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 中创建字符串时会出现内存泄漏?的主要内容,如果未能解决你的问题,请参考以下文章