16

所以我正在调试一个应用程序,为它的应用程序发布做准备,我为“所有异常”启用了一个通用断点。从那时起,每次我运行应用程序时,控制台都会打印:

Catchpoint 2 (throw)Pending breakpoint 1 - "objc_exception_throw" 已解决

objc [11765]:__NSCFLocale 类的对象 0x8f18ff0 自动释放,没有适当的池 - 只是泄漏 - 在 objc_autoreleaseNoPool() 上中断以进行调试

objc [11765]:__NSCFNumber 类的对象 0x8f190a0 自动释放,没有适当的池 - 只是泄漏 - 在 objc_autoreleaseNoPool() 上中断以进行调试

objc [11765]:__NSCFLocale 类的对象 0x8f1fef0 自动释放,没有适当的池 - 只是泄漏 - 在 objc_autoreleaseNoPool() 上中断以进行调试

字面印刷3次。我不知道这意味着什么,但看起来很糟糕。任何意见,将不胜感激。

4

3 回答 3

35

新信息

我通过创建一个混合的自动释放方法来确定我的问题所在。

除非您知道自己在做什么,否则我不建议您这样做,但是这是我发现的。

+ (void) load; //Method is called outside the original autorelease pool.
+ (void) initialize; // Method is called outside the original autorelease pool.

NSThread 创建自己的线程,被调用的方法应该包装在一个自动释放池中。

当使用“dispatch_...”命令时,Grand Central Dispatch 负责适应自动释放池。但是,当您手动发送时。您可能希望将其包装在自动释放池中。

此外,ARC 不会让您知道自动释放将在池外发生。

因此,如果您使用 ARC 并且知道您将在自动释放池之外。你对此无能为力。您将要避免所有方便的方法。

用这个。

[[NSString alloc] initWithFormat:@"%@",myObject];

而不是这个

[NSString stringWithFormat:@"%@",myObject];

这将允许 arc 系统保留和释放,但通过便捷方法完成的底层自动释放将被跳过,因为您不会使用便捷方法。

希望有帮助。

原始答案

好的,我觉得这个问题的回答不够详细。

呈现的信息是

objc[1310]: Object 0x34f720 of class SimpleKeychain autoreleased with no pool in place - just leaking - break on objc_autoreleaseNoPool() to debug

调试器指出了一个可能的断点,可以帮助您调试情况。现在虽然这个断点对调试情况几乎没有帮助。我认为知道如何将断点添加到调试器很重要,因此我花时间修补它(在搜索互联网并一无所获之后),直到我让它打破那个错误。

中断所有错误并没有捕捉到这一点有点烦人,但这里是将断点添加到调试器的步骤。

您要做的第一件事是选择调试器的断点导航器

导航工具栏

通过单击此选项卡

断点按钮

接下来,您查看导航器窗格的底部并按加号按钮

添加异常断点

这将允许您手动添加断点。

我选择了一个 C++ 断点并将消息名称输入到名称文本字段中。

添加自定义 C++ 异常

添加此异常后,它实际上确实中断了。

但是,这对作为 Objective C 开发人员的您可能有用,也可能没用。这闯入了汇编代码。

实现断点处的汇编代码。

不幸的是,它只在线程的调用堆栈上显示了这一点。

线程列表

事实证明,自动释放问题是因为在 dispatch_once 调用中有一个名为 autorelease 的类。进一步调查显示 +(void) 负载;类上的方法在其他任何事情之前被调用。这是通过 call_load_methods 函数完成的,并且位于 main 方法的线程之外。

错误调用和堆栈

为了纠正这个问题,我只是在调用周围添加了自动释放池包装器。

更新错误调用

另一种解决方案可能是在 +(void)load 中添加自动释放池;方法。但这对我的用途来说已经足够了。

注意:我将其添加到此处的帖子中,因为我不喜欢发现问题并且无法找出结果答案的所有路径。如果调试器告诉您向列出的函数添加断点,那么在某处应该有一些信息可以获取该信息。希望这会降低一些试图找到这个答案的人的挫败感。

于 2012-06-05T20:31:18.247 回答
1

cocoa api 中的许多方法都返回自动释放的对象。特别是那些返回不以 开头的对象的方法init,例如[NSNumber numberWithLong:]. 如果您没有适当的自动释放池,这些对象将被泄露。NSAutoreleasePool您可以在文档中找到有关使用的更多信息。

于 2012-04-04T01:58:57.023 回答
1

这意味着您需要在它发生的线程上创建一个自动释放池。否则,您分配的对象将不会被销毁(如消息所示)。因此,在符号处中断/暂停,然后将堆栈向上移动到您的线程(或程序)条目并添加一个自动释放池。就这样。

于 2012-04-04T02:20:45.420 回答