Mac Cocoa:无法释放窗口以取回其内存

Posted

技术标签:

【中文标题】Mac Cocoa:无法释放窗口以取回其内存【英文标题】:Mac Cocoa: Can't release a window to get back its memory 【发布时间】:2012-11-23 01:10:58 【问题描述】:

我有一个使用 ARC 用 Cocoa 编写的应用程序,它允许用户创建和打开新窗口。 (它就像一个文档模型,但我没有使用 nsdocument。

每个新窗口都需要大量内存,如果用户关闭窗口,我想取回这些内存。

我知道[window close] 只是隐藏了窗口,但我也在使用[[self window] setReleasedWhenClosed:YES],但NSwindowcontroller 及其窗口在关闭后仍然存在。

我窗口的 xib 文件中的对象包含许多用 malloc 分配的大型 c 数组,因此我还尝试通过向窗口控制器的 windowWillClose: 方法内的通知中心发送调用来释放它们,其中通知调用相关对象中的方法在窗口关闭之前释放 C 数组。同样,这是没有效果的——即使尝试释放数组的方法被调用并且数组显然被释放,根据活动监视器,没有内存被释放。我也尝试过释放-(void) dealloc 中的数组,但这似乎永远不会在关闭时调用。

那么,当窗口关闭时,我怎样才能最好地恢复内存呢?

编辑:根据 Benoit 对this *** page 的评论,

“但是,窗口控制器拥有的窗口会忽略关闭时的释放。”

这是真的吗?如果是这样,我怎样才能在 ARC 中解决这个问题?

【问题讨论】:

【参考方案1】:

释放的内存不能总是返回给操作系统。这只是生活中的事实,至少在没有压缩垃圾收集器的系统上是这样。

不要注意 Activity Monitor 中的统计信息,除非您完全了解您正在查看的内容。除非您对系统有相当透彻的了解,否则这些信息通常没有用处——包括虚拟内存、共享库占用的内存部分以及您正在使用的分配器的行为。 NSArrayNSMutableArray 类在分配方面有一些相当不透明的行为,顾名思义,它们通常不是线性数组。

建议:只要你的窗口被释放,忽略活动监视器中的统计信息。您可以使用 Instruments 来检查泄漏。

作为一个为什么应该忽略活动监视器的示例:如果您在 1 KiB 块中分配 500 MiB,然后释放奇数块,显然它们无法返回给操作系统,因为页面在大多数现代系统上,粒度最小为 4 KiB。如果您在 1 MiB 块中分配相同的 500 MiB 并释放奇数块,它们将返回给操作系统,并且内存使用量将减少 250 MiB,如 Activity Monitor 报告的那样。 (请注意,4 KiB 阈值不是发生此行为的阈值。它取决于malloc() 的确切分配行为,以及在 OS X 上取决于 CPU 和 RAM 数量的一些参数。)

但是,这可能无关紧要。在每种情况下,如果您再次分配 250 MiB,您将回到开始的位置。使用较少的私有内存固然很好,但这只会影响您的应用程序与其他应用程序的交互效果。

【讨论】:

谢谢,但我不确定我的 2009 版 macbook 是否强大到足以运行 Instruments。我让它结结巴巴,让笔记本电脑风扇超速运转大约 10 分钟,监控一个窗口的打开情况,这通常需要大约 5 秒钟,而 Instruments 没有运行。 @ChristianJ.B.:嗯,这很有趣。我 2005 年的 mac 可以很好地运行它...... 我正在运行 Instruments->如果有帮助的话会泄漏。 @ChristianJ.B.:作为“穷人的泄漏检测器”,您可以打开和关闭几个窗口,测量内存使用情况,然后打开和关闭更多的窗口(但永远不会有更多的窗口同时打开)。如果在您打开和关闭窗口时内存使用量持续上升,则说明存在泄漏。 @ChristianJ.B.:如果你不能运行 Instruments,那我不知道该说什么。尝试询问有关 Instruments 检漏仪为何不工作的问题。在我的低端 MacBook Air 上使用检漏仪时,我发现没有明显的性能下降——一切都和以往一样流畅。

以上是关于Mac Cocoa:无法释放窗口以取回其内存的主要内容,如果未能解决你的问题,请参考以下文章

XCode/Cocoa Mac 改变视图

Cocoa 无法在没有托管对象上下文的情况下执行操作

Cocoa Xcode:使用 Swift 4 for Mac 以编程方式从 AppDelegate 打开窗口控制器?

C#无法访问已释放的对象

Cocoa - 如何以编程方式初始化视图?

为什么Mac应用程序无法正常运行了