我正在编写一个通用的Swift应用程序(不适用于iOS,它稍后将在raspbian上运行(,我注意到内存不断增加。我也和检查员一起检查了内存泄漏,但没有。为了更深入地研究,我为macOS创建了一个空白应用程序,我只写了几行代码,这些代码只用于测试:
var array = [Decimal]()
while(true) {
array = [Decimal]()
for i in 0..<10000
{
array.append(Decimal(string: i.description)!)
}
sleep(1)
}
正如我所知,在while循环的每个循环开始时,上一个循环中填充的整个数组都应该从内存中删除。但这似乎并没有发生,有了这些代码行,进程内存就会无限期地增加。
我还在一个iOS项目上尝试了同样的代码,将其放在应用程序函数(在应用程序委托中一开始调用的函数(上,我注意到在这种情况下,内存保持不变,不会上升。
我在非iOS项目上遗漏了什么吗?
Decimal(string:)
正在创建自动释放对象。使用autoreleasepool
定期排空池:
var array = [Decimal]()
while true {
autoreleasepool {
for i in 0..<10_000 {
array.append(Decimal(string: i.description)!)
}
sleep(1)
array = []
}
}
通常情况下,当您返回到运行循环时,自动释放池会被耗尽。但在这种情况下,这个while
循环永远不会返回到操作系统,因此池不会耗尽。使用您自己的autoreleasepool
,就像上面一样,解决了这个问题。
FWIW,苹果公司一直在慢慢地禁止在Foundation/Cocoa类中使用自动释放程序对象。(我们过去遇到这个问题的Foundation对象/API比现在多得多。(很明显,Decimal(string:)
仍然在幕后创建自动发布对象。在大多数实际情况下,这不是问题,但在您的示例中,您需要引入自己的autoreleasepool
来缓解while
循环中的这种行为。