【问题标题】:How to break on __NSAutoreleaseNoPool如何打破 __NSAutoreleaseNoPool
【发布时间】:2013-05-17 21:00:40
【问题描述】:

我越来越兴奋了

*** __NSAutoreleaseNoPool(): NSEvent 类的对象 0x1961180 自动释放,没有适当的池 - 只是泄漏

运行时的警告,不知道原因是什么。粗略的谷歌表明这是一个我可以用 Xcode 中断的符号,但是通过 Run>Manage Breakpoints>Add Symbolic Breakpoint 将它添加为符号断点,或者只是通过断点管理窗口,会产生一个带有 - 旁边的断点而不是支票,我认为这是一个找不到的符号。

我试过用两个下划线,一个下划线添加符号“__NSAutoreleaseNoPool”,现在我只是觉得很愚蠢。错误继续被记录并且没有断点被命中。任何打破 Obj-C 符号或调试的指针都将不胜感激。

[编辑:在可能 10 次(10 次以上,所以总共有几十次,包括至少两次 Xcode 重启)运行后,我在控制台上打印了“待定断点 9 - “__NSAutoreleaseNoPool”已解决”,断点开始工作。有什么方法可以强制一个挂起的断点真正解决?]

【问题讨论】:

    标签: debugging macos


    【解决方案1】:

    要真正回答您的问题,请查看NSDebug.h。在那里你会发现这是其中一部分的评论:

    NAME OF ENV. VARIABLE                  DEFAULT  SET TO...
    NSDebugEnabled                            NO    "YES"
    NSZombieEnabled                           NO    "YES"
    NSDeallocateZombies                       NO    "YES"
    NSHangOnUncaughtException                 NO    "YES"
    

    下面是这些 cmets:

    // Functions used as interesting breakpoints in a debugger
    // void __NSAutoreleaseNoPool(void *object);
            // Called to log the "Object X of class Y autoreleased with no
            // pool in place - just leaking" message.  If an environment
            // variable named "NSAutoreleaseHaltOnNoPool" is set with string
            // value "YES", the function will automatically break in the
            // debugger (or terminate the process).
    
    // void __NSAutoreleaseFreedObject(void *freedObject);
            // Called when a previously freed object would be released
            // by an autorelease pool.  If an environment variable named
            // "NSAutoreleaseHaltOnFreedObject" is set with string value
            // "YES", the function will automatically break in the debugger
            // (or terminate the process).
    

    所以你真的不需要设置这些断点;只需设置适当的环境变量。你可以从你的例如做后者。 .bashrc 或在 Xcode 4 中,您可以编辑“方案”的“运行”部分并将它们设置在那里——这就是我所做的,它工作得很好。

    【讨论】:

    • 我发现将 NSDeallocateZombies 设置为 NO 最有用。否则,它们将被释放!然后他们就不能发挥他们的僵尸功能了。如果您的内存完全耗尽,将其设置为 YES 是一种临时补丁。
    【解决方案2】:

    我在 __NSAutoreleaseNoPool() 上设置断点时遇到了同样的问题。 我终于成功设置断点使用 gdb 命令。 调试器启动后,在调试器控制台中按 ctrl+C。 使用“br __NSAutoreleaseNoPool”设置断点并重启调试器。

    【讨论】:

      【解决方案3】:

      听起来您在某个线程中使用 Cocoa,而不是使用自动释放池包装线程主体。您可能不需要使用断点来找到它。你在做任何 detachNewThreadSelector 吗?

      【讨论】:

      • 断点最终确实开始工作了(在经历了这次考验之后,我没有选中“懒惰地加载符号”复选框......这是我每次新安装时都会忘记的东西;我希望这不是默认设置)。问题似乎更多是我正在使用的图形库(SFML)在我从计时器调用它的绘制和更新调用时在我现有的运行循环中启动它自己的运行循环(这样做是为了不阻止本机 UI元素)。这混淆了 Cocoa 和调试,但我的内存使用并没有像我预期的那样爆炸,所以也许这是我可以摆脱的(内部开发工具)。
      • 这解决了我的问题。在我使用 performSelectorInBackground 调用的方法(选择器)中,我必须将主体包装在 NSAutoreleasePool 中。
      【解决方案4】:

      这里的问题很简单:您在没有池的情况下发布。这通常发生在针对 Foundation 编写的命令行工具中。只需将以下代码添加到您的main():(无关部分省略)

      int main (…) {
        NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
      
        /// Your code goes here.
      
        [pool drain]; // This one might not strictly speaking be neccessary.
        [pool release];
      
         return 0;
      }
      

      编辑:如果您没有创建命令行工具,那么您很可能在做一些顽皮的事情;但尽管如此:如果您有在 NSApplicationMain() 之前调用的代码,则需要将其包装在相同的基本代码中,在调用 NSApplicationMain 之前排空和释放池。

      【讨论】:

      • 虽然我最初的问题更多地与断点有关,但我仍然纠结于此。现在我真的要崩溃了,我看到了以下堆栈,正如你所看到的,我的 NSApplicationMain 周围有一个自动释放池,并且在运行时仍然收到 NSNoAutoreleasePool 错误,我的代码(在 main 之外)都没有被执行:not-included.net/gfx/stupid/NSNoAutoReleasePool.png 关于自动释放池的旁白:为什么有这个必要?主运行循环的自动释放池不应该处理这个吗?
      • 另一个面包屑,这也会在每个“没有池到位”错误之后打印。恢复了最近的任何更改,它仍然显示;我想我之前没有注意到:>***尝试弹出一个未知的自动释放池(0x89ac00)
      • 啊。好吧,自动释放池不应该在NSApplicationMain() 附近。该特定函数处理自己的池。
      • @Williham Totland:它也不会造成任何伤害。
      • @Ivan:嗯,这离话题太远了。 :P IMO:每个周期都很重要。你不同意。我将不得不选择“随便”,交易?
      【解决方案5】:

      我知道这是一个旧线程。只是想分享一些关于正确解决方案的信息。 在 _autoreleasenopool 处设置断点的正确方法是使用 xcode 中的断点导航器。(使用键盘命令+6)。 在断点导航器的左下角单击“+”号并添加符号断点。输入符号为 objc_autoreleaseNoPool。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-12-31
        • 2022-01-10
        • 1970-01-01
        • 1970-01-01
        • 2013-03-27
        • 2010-09-23
        相关资源
        最近更新 更多