Can't find memory leak in Swift app

I'm trying to learn Swift and so I wrote a little test app for that. It just gives the total size of the items in a directory, recursively into subdirectories to copy the total size of their content. The app works, but memory usage just goes up and up as it runs. I expected the memory usage to increase as the recursion gets deeper and decrease when the recursive call returns. Instead, memory usage just goes up constantly. Instruments do not identify leaks. I've tried a few tips I've found in various google results, including:

reuse the default NSFileManager do not reuse the default NSFileManager, but create a new one for each recursive call avoiding string interpolation

Nothing matters. I thought Swift would clear objects as their countdown reaches zero.

This is the complete code as it stands:

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)")
                }
            }
        }
    }
}

      

+3


source to share


1 answer


You need to add autoreleasepool in a loop, perhaps around a recursive call. Since it is a closed loop, the wait loop does not receive any changes to free temporary memory allocations.

Example:



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

      

+2


source







All Articles