【问题标题】:Why is NSOpenPanel/NSSavePanel showing memory leak?为什么 NSOpenPanel/NSSavePanel 显示内存泄漏?
【发布时间】:2011-10-22 15:54:33
【问题描述】:

不知道为什么,但是制作一个简单的[[NSOpenPanel openPanel] runModal]; 会造成内存泄漏 - 在 Leaks Instrument 中可以看到。

好像没了。

这是一个自动释放的对象,不是应该在ARpool耗尽后自动释放吗?

有没有办法解决这个问题?

【问题讨论】:

    标签: objective-c cocoa xcode4 nsopenpanel nssavepanel


    【解决方案1】:

    NSOpenPanel 是一个单例,这意味着每次使用它时总是会得到相同的对象实例。这意味着当您第一次调用[NSOpenPanel openPanel] 时,会创建一个NSOpenPanel 的实例而不是释放。

    这不是泄漏,而是优化。但是,有时 Leaks 工具会将此类仅一次性实例化为泄漏,因为这些实例(根据设计)从未释放。

    NSOpenPanel 是一个如此广泛使用和经过测试的类,其标准实现中的任何泄漏都不太可能存在。

    【讨论】:

    • 有没有办法阻止 Xcode Instruments 记录单例?
    • 这根本不好 :( 我还注意到在Mac Activity Monitor 中,当我使用NSOpenPanel 时,我的应用程序的内存增加了,当我关闭它时,内存仍然处于同一水平不会减少...
    • 不要使用活动监视器进行分析。您必须预计您的应用程序会在某些点使用更多内存,并且在NSOpenPanel 的情况下,内存增加应该只发生一次。别担心了。
    • @RobKeniger 在我的情况下,我的一个应用增加了 20MB,而另一个增加了 40MB,你知道原因吗?
    • 至少对于 Xcode 8.1 和 macOS 10.12 SDK 这不是真的。 NSSavePanel 的每次打开和关闭都会泄漏新的内存。由于“单例”性质,这不是一次性泄漏。我在自己的代码中多次创建了单例,但它们从未在泄漏工具中显示为泄漏。
    【解决方案2】:

    NSOpenPanel 不是单例。可能有过一次,但查看最新的 NSOpenPanel.h 文件可以清楚地表明它不是单例,或者至少 Apple 不希望您利用此实现细节。

    至于泄漏,我对何时应该释放打开的面板并保留它感到困惑。从文件系统编程指南的Using the Open and Save Panels 部分,您的生活在 10.7 及更高版本中变得更加轻松:

    Important: In OS X 10.6 and earlier, you must retain an open panel prior to displaying it and release it when you are done with it. Because the openPanel method returns an autoreleased object, the panel is normally released shortly after it appears on screen. Retaining the panel prevents it from being deallocated and dismissed prematurely. You do not need to retain the panel if it is attached to a window and you do not need to retain the panel in OS X 10.7 and when using ARC.
    

    一旦我不再保留它,事情就变得容易了,变得容易多了:)

    【讨论】:

      【解决方案3】:

      仪器在检测泄漏方面并不完美 - 特别是对于自动释放的对象,并且有误报的趋势。您可以尝试创建一个新的 NSAutoreleasePool,然后在完成 NSOpenPanel 后将其排空以强制提前释放 - 但我怀疑您实际上并没有泄漏。如果您确信代码看起来不错并且是自动发布的,那么它可能没问题。

      【讨论】:

      • 这是我唯一的代码。只是想知道这是否是应该报告的 OSX 错误。
      • 我所读到的关于 Instruments 内存泄漏检测的所有信息都是它可能导致自动释放池的误报。我想报告它并没有什么坏处,但最好先在 Apple 论坛上提问。
      【解决方案4】:

      在使用 10.12 SDK 和 Swift 3.0.1 在 OS X 10.11.6 上构建的非沙盒应用程序中使用 NSOpenPanel 时,我看到 Xcode 的内存图工具中报告了“泄漏”。 “泄漏”是在 PlugInKit 类(PKHostPlugin、PKDiscoveryDriver 等)中报告的,即使唯一的代码行是 let openPanel = NSOpenPanel(),也会显示出来。

      NSOpenPanel's documentation states

      在沙盒环境中,打开的面板绘制在单独的 由 powerbox 处理,而不是由 AppKit 本身处理。当用户选择一个 要打开的文件,macOS 会将该文件添加到应用程序的沙箱中。

      在我对应用程序进行沙盒处理后,“泄漏”并没有出现在 Xcode 的内存图中,因为 NSOpenPanel 实现代码不再在应用程序的地址空间中,所以我不再需要担心了。

      【讨论】:

        猜你喜欢
        • 2014-10-24
        • 2012-06-20
        • 2011-10-25
        • 1970-01-01
        • 1970-01-01
        • 2016-01-02
        • 1970-01-01
        • 1970-01-01
        • 2011-03-05
        相关资源
        最近更新 更多