Xcode异常断点不打印抛出的异常细节

63

摘要

当我设置异常断点时,我没有得到异常消息。如何获得异常消息?我已经知道如何获取堆栈跟踪,但这并不包括异常消息。

详情

过去我使用Xcode开发iOS应用程序时,如果出现问题,我会收到一个错误/异常。异常通常会有像“无法取消引用null”之类的消息。

现在,使用Xcode 4.6.x已经几周了,我从来没有收到过异常消息。我经常会收到SIGABRT。我在异常断点处打了断点,它会在某些内部iOS SDK的汇编代码中停下来,但我从未收到过消息。

事实上,我不记得上一次在调试器控制台中看到任何东西了。

随着迁移到LLVM,异常信息是否消失了?

我的应用程序在SDK中崩溃而不知道原因是非常令人沮丧的。我检查最后一个函数以确保设置正确(对象已分配等等),它们是正确的,这意味着我没有线索。

可能是从过去继承下来的构建设置以某种方式关闭了异常消息吗?

请重新打开问题,它现在有答案了!

在评论中给出了一个很好的答案。这应该被提升为完整答案,这样我就可以标记问题已答复,其他遇到此常见问题的人也可以找到它。为了实现这一点,需要重新打开问题!(打开后我会删除这个请求。)


4
在这个断点中,您是否将bt作为操作?右键单击->编辑断点->操作->在下拉菜单中选择“调试器命令”,在文本字段中输入bt。 这样应该会在控制台中打印回溯信息。 - Kreiri
1
@grasGendarme:“我在异常断点上加了一个中断”,这有点暗示OP已经有一个了。 - Kreiri
3
如果你设置了异常断点,那么在异常被打印到控制台之前就会触发断点。我会在这里解释如何设置断点以打印异常信息(链接为http://qwan.org/2013/06/18/how-to-snatch-the-error-code-from-the-trap-frame-in-xcode/)。 - rob mayoff
2
你看过我之前给的链接吗?因为我曾经被完全相同的问题困扰过,而在2013年的WWDC上,我得到了lldb团队成员的帮助来解决它。我在那个链接中解释了如何解决这个问题。 - rob mayoff
2
如果这个问题被重新打开,我会回答的。 - rob mayoff
显示剩余13条评论
6个回答

66
我会在此处更新Jeff的答案:
为了突出异常的代码行(而不是main.m中的UIApplicationMain()),并且看到异常的原因(例如,"error: A fetch request must have an entity."),请执行以下操作:
  • 在“断点导航器”中:
    1. 添加(+), 添加异常断点
    2. 选择新断点,控制-单击,编辑断点
    3. 添加动作
    4. 输入:po $arg1
相关部分的堆栈跟踪将在导航器区域中。
这似乎在Xcode 9中仍然有效。
以下是我针对Xcode 6及以下版本的补充说明。
  • 输入:po (NSException*) $eax
  • 在Xcode 6中,必须明确提供对象类型,因为它不再被推断。

    或者,您也可以进入控制台窗口并在调试控制台中输入po(NSException*)$eax。 - ucangetit
    13
    重要提示:如果您正在创建 64 位应用程序,则请改用 $rax 而非 $eax。po (NSException*)$rax 的翻译是:“显示(打印)$rax 中的 NSException* 对象”。 - Rickster
    7
    在Xcode 6.3中我得到了错误结果:使用未声明的标识符"$eax",rax也是同样。我做错什么了吗? - Heps
    7
    在 Xcode 8 中使用 Swift,当输入 po $arg1 后会输出一个像 106102873062904 这样的大数字,这是什么意思?我该如何打印指向的字符串? - DawnSong
    1
    最好编辑原始答案而不是复制粘贴和补充。然而,可以确认:在Xcode 9上执行po $arg1是成功的。 - Max MacLeod

    52

    针对 Xcode 7-9 (基于 Jeff 的回答):

    在断点导航器中:

    1. 添加(+),添加异常断点
    2. 选择新的断点,使用控制键点击,编辑断点
    3. 添加操作
    4. 输入:po $arg1

    2
    在XCode 7.3中,出现了“错误:使用未解决的标识符'$arg1'”的提示。 - fishinear
    1
    Xcode 8,Swift 2.3,它打印了一个大数字。在Swift中我该怎么做?谢谢。 - DawnSong
    @DawnSong 这可能是一个 C++ 异常,你可能不需要担心它。 - marosoaie
    1
    谢谢你的提示。我一直在使用“po $eax”,但是没有得到任何结果。回报一下:如果你右键点击异常,然后滚动到“移动断点到”并选择用户,该异常将适用于所有项目,而不仅仅是当前项目。这样可以避免记住一个小细节。 - PruitIgoe
    3
    如果在Swift中执行“do po $arg1”将不会打印任何有用的信息,因此将异常部分从All更改为Objective-C。 - Hosny

    12

    若想要同时突出显示导致异常的代码行(而不是在main.m中的UIApplicationMain()函数),以及查看异常原因(例如:“错误:获取请求必须有实体”),请执行以下操作:

    • 在断点导航器中:
      1. 添加(+),添加异常断点
      2. 选择新断点,按Control键单击,编辑断点
      3. 添加操作
      4. 输入:po $eax

    与堆栈跟踪相关的部分将显示在导航器区域中。


    4
    我已经在多个地方看到这条建议……但在Xcode 6中它不再起作用了。 - bradheintz

    6

    是的,xcode在调试时不太友好。我喜欢这篇文章,它帮助我更清楚地理解崩溃日志。

    Demystifying iOS Application Crash Logs

    如果看到“向已释放实例发送消息”的错误,请执行以下操作:

    '产品 -> 编辑方案 -> 启用僵尸对象'

    这将启用僵尸对象功能,当您对项目进行profile时,选择“僵尸”,引发错误并且您就可以看到哪些对象被释放了,例如 NSArray *myArray。


    有趣的是,以下选项之一“启用僵尸对象”是“记录异常”,以前没有被选中。我已经勾选它,看看是否解决了问题。 - nirvana

    5

    当没有异常断点设置时,我从po $eaxpo (NSException *)$eax得到的信息似乎与Xcode打印的不同。因此,我进行以下操作:

    1. 添加异常断点
    2. 异常发生,断点被触发 -> 我知道位置了
    3. 暂时禁用断点(在调试区域左侧的第二个按钮)
    4. 继续程序执行(在调试区域左侧的第三个按钮)
    5. 详细信息被打印出来 -> 我知道原因了

    显然这并不是很优雅和灵活,但至少我解决了两个重要问题(位置和原因)。


    感谢您的提示:“继续程序执行(调试区域左侧的第三个按钮)”。我之前一直在重新启动应用程序并希望出现相同的异常。使用Xcode 10。 - Jeff

    5

    LLDB线程回溯

    [低级虚拟机(LLVM)]

    您可以使用btthread backtrace命令打印错误跟踪

    显示当前线程的堆栈回溯。

    您可以在崩溃报告中找到相同的堆栈跟踪

    enter image description here

    关于当前线程使用的信息 currentThread

    //Objective-C
    po [NSThread currentThread]
    
    //Swift
    po Thread.currentThread
    

    有时候当 po 无法工作时,可以使用 fr v (或来自 XCode 10.2 的 v

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接