我有一个用ARC用Cocoa编写的应用程序,它允许用户创建和打开新窗口。(这就像一个文档模型,但我没有使用nsdocument。)
每个新窗口都需要大量的内存,如果用户关闭窗口,我希望能恢复这些内存。
我知道[window close]
只是隐藏窗口,但我也在使用[[self window] setReleasedWhenClosed:YES]
,但NSwindowcontroller
及其窗口在关闭后仍然存在。
我的窗口的xib文件中的对象包含许多用malloc分配的大型c数组,因此我还尝试通过向windowcontroller的windowWillClose:
方法内的通知中心发送调用来释放它们,在该方法中,通知调用相关对象内的方法,以在窗口关闭前释放c数组。同样,这是无效的——根据活动监视器的说法,尽管调用了试图释放数组的方法,并且显然释放了数组,但从未释放过内存。我也尝试过释放-(void) dealloc
中的数组,但这似乎从未在关闭时调用过。
那么,当窗户关上的时候,我该如何才能最好地找回记忆呢?
编辑:根据Benoit对这个stackoverflow页面的评论,
"但是,对于窗口控制器拥有的窗口,关闭时释放被忽略。">
这是真的吗?如果是这样,我该如何在ARC中绕过这一点?
释放的内存不能总是返回到操作系统。这只是生活中的一个事实,至少在没有压缩垃圾收集器的系统中是这样。
除非您确切地了解所查看的内容,否则不要关注活动监视器中的统计信息。除非您对系统有相当全面的了解,否则这些信息通常不会有用,包括虚拟内存、共享库占用了内存的哪一部分,以及您正在使用的分配器的行为。当涉及到分配时,NSArray
和NSMutableArray
类有一些相当不透明的行为,它们通常是而不是顾名思义的线性数组。
建议:只要您的窗口被释放,就忽略活动监视器中的统计信息。您可以使用仪器来检查是否存在泄漏。
举个例子说明为什么应该忽略活动监视器:如果你在1 KiB块中分配500 MiB,然后释放奇数块,显然它们不能返回到操作系统,因为在大多数现代系统上,页面粒度最小为4 KiB。如果您将相同的500 MiB分配到1 MiB块中,并释放奇数块,它们将返回到操作系统,内存使用率将下降250 MiB,正如活动监视器所报告的那样。(请注意,4 KiB阈值不是发生这种行为的阈值。它取决于malloc()
的确切分配行为,以及一些参数,在OS X上,这些参数取决于CPU和RAM的数量。)
然而,这可能无关紧要。在每种情况下,如果你再次分配250 MiB,你就会回到你开始的地方。使用较少的私有内存是件好事,但这只会影响您的应用程序与其他应用程序的交互效果。