swift - 为什么 FileManager.enumerator 使用了荒谬的内存量?

标签 swift macos memory-leaks nsfilemanager

有没有人知道为什么以下代码使用了荒谬的 4.75 GB 内存?

有没有更好的方法来循环文件系统中的所有文件? (我试图找到驱动器上最大的文件)

let filemanager:FileManager = FileManager()
let root = "/"
let files = filemanager.enumerator(atPath: root)
while let element = files?.nextObject() {
    // do nothing
}

注意:我的文件系统上有 400k 个文件(没什么特别的)。代码是连续的,所以理论上它甚至不应该依赖于文件的数量。

最佳答案

我用内存图暂停了它,它显示了荒谬数量的 NSConcreteData 实例,分配自 fileSystemRepresentation(withPath:) .

该文档页面指出,它是一个仅适用于当前自动释放池的指针。这提出了一个解决方案:我们只需要让 nextObject() 调用进入它自己的自动释放池。

例如,这个程序稳定在 11.0 MB:

var done = false
while !done {
    autoreleasepool {
        let element = files?.nextObject()
        done = (element == nil)

        // do nothing
    }
}

看起来 Swift 的 while let 语法将绑定(bind)放入 while 循环上下文的自动释放池中,因此每个元素都将保留到整个循环完成为止。

通过强制枚举器的对象进入我们自己的自动释放池,我们可以确保它不会在后续迭代中保留。

编辑:因为 autoreleasepool 只是一个函数,我本可以写得更简洁:

while let element = autoreleasepool(invoking: { files?.nextObject() }) {
    // do nothing
}

关于swift - 为什么 FileManager.enumerator 使用了荒谬的内存量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46383143/

相关文章:

objective-c - 使用自己用 objective-c 编写的应用程序打开文件

ios - 在 Firebase 中创建一个以前不存在的新文件 - Swift

swift - 如何防止 willDisplay 单元格 : from being called when I reload a UICollectionView's data?

macos - 正确地将对象移至垃圾箱

c++ - ld : symbol(s) not found for architecture

BFS 实现中的 Haskell 空间泄漏

ios - 如何将 AWS DynamoDB 与数据集 ios swift 同步?

swift - 子类化格式化程序在初始化程序上崩溃

java - 我需要显式释放 FullHttpRequest.content().copy() 吗?

c++ - 使用 CoCreateInstance 时内存泄漏