【问题标题】:Can't find memory leak in Swift app在 Swift 应用程序中找不到内存泄漏
【发布时间】:2014-09-09 23:38:33
【问题描述】:

我正在尝试学习 Swift,因此为此我编写了一个小测试应用程序。它只是给出目录中项目的总大小,递归到子目录以累积其内容的总大小。应用程序可以运行,但内存使用量只会在运行时不断增长。我曾预计内存使用量会随着递归的深入而增加,并在递归调用返回时减少。相反,内存使用量不断攀升。 Instruments 没有发现任何泄漏。我尝试了一些在各种谷歌搜索结果中发现的提示,包括:

重用默认的 NSFileManager 不重新使用默认的 NSFileManager 而是为每个递归调用创建一个新的 避免字符串插值

似乎没有任何区别。我原以为 Swift 会在引用计数为零时清理对象。

这是当前状态下的完整代码:

import Foundation

func sizeOfContents(path: String) -> UInt64
{
    let subManager = NSFileManager()
    var totalSize: UInt64 = 0;
    var isDir: ObjCBool = false
    if subManager.fileExistsAtPath(path, isDirectory: &isDir)
    {
        if !isDir.boolValue
        {
            var error: NSError? = nil
            let attributes: NSDictionary? = subManager.attributesOfItemAtPath(path, error: &error)
            let size: UInt64? = attributes?.fileSize()
            totalSize += size!
        }
        else
        {
            var error: NSError? = nil
            if let subContents = subManager.contentsOfDirectoryAtPath(path, error: &error)
            {
                for subItem in subContents
                {
                    var subName = subItem as String
                    subName = path + "/" + subName
                    totalSize += sizeOfContents(subName)
                }


            }
        }
    }

    return totalSize
}

let manager = NSFileManager.defaultManager()
var rootPath = "/Applications/"
if let contents = manager.contentsOfDirectoryAtPath(rootPath, error: nil)
{
    for item in contents
    {
        let itemName = item as String
        var isDir: ObjCBool = false
        print("item: " + (rootPath + itemName))
        if manager.fileExistsAtPath(rootPath + itemName, isDirectory: &isDir)
        {
            if !isDir.boolValue
            {
                var error: NSError? = nil
                let attributes: NSDictionary? = manager.attributesOfItemAtPath(rootPath + itemName, error: &error)
                let size: UInt64? = attributes?.fileSize()
                println("\t\(size!)")
            }
            else
            {
                if(itemName != "Volumes")
                {
                    let size = sizeOfContents(rootPath + itemName)
                    println("\t\(size)")
                }
            }
        }
    }
}

【问题讨论】:

    标签: recursion memory-leaks swift


    【解决方案1】:

    您需要在循环中添加一个自动释放池,可能围绕递归调用。由于它是一个紧密循环,因此空闲循环不会改变以释放临时内存分配。

    示例:

    ...
    autoreleasepool {
        totalSize += sizeOfContents(subName)
    }
    ...
    

    【讨论】:

    • 就是这样。现在我必须去阅读关于 autoreleasepool 的内容。当我从“/”开始运行该应用程序时,该应用程序现在从未超过 6.4MB,之前它超过了 60GB,并且运行速度要快得多。它从未在 Swift Programming Language 书籍中提及它,但我确实在 WWDC 会议(Improving Your App With Instruments)中找到了一些关于它的内容。非常感谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-07
    • 1970-01-01
    相关资源
    最近更新 更多