Xcode / LLDB:如何获取有关刚刚抛出的异常的信息?


83

好的,所以想象一下我的断点objc_exception_throw刚刚触发。我坐在调试器提示符下,我想获得有关异常对象的更多信息。我在哪里找到它?


2
请记住,该异常刚刚被提出,其描述尚未打印在控制台上。
卡罗伊·洛伦蒂

Answers:


162

异常对象作为第一个参数传入objc_exception_throw。LLDB提供了$arg1..$argn变量来引用正确的调用约定中的参数,从而使打印异常详细信息变得简单:

(lldb) po $arg1
(lldb) po [$arg1 name]
(lldb) po [$arg1 reason]

objc_exception_throw执行这些命令之前,请确保在调用堆栈中选择框架。请参阅WWDC15会话视频中的“高级调试和地址清理器”,以查看在舞台上执行的操作。

过时的信息

如果您使用的是GDB,则引用第一个参数的语法取决于您所运行的体系结构的调用约定。如果您是在实际的iOS设备上调试,则指向该对象的指针位于register中r0。要打印或向其发送消息,请使用以下简单语法:

(gdb) po $r0
(gdb) po [$r0 name]
(gdb) po [$r0 reason]

在iPhone Simulator上,所有函数参数都在堆栈上传递,因此语法更加可怕。我能构造的最短表达式是*(id *)($ebp + 8)。为了减轻痛苦,我建议使用便捷变量:

(gdb) set $exception = *(id *)($ebp + 8)
(gdb) po $exception
(gdb) po [$exception name]
(gdb) po [$exception reason]

您还可以$exception通过向断点添加命令列表来在触发断点时自动进行设置objc_exception_throw

(请注意,在我测试过的所有情况下,断点命中时,eaxand对象中都存在异常对象edx。不过,我不确定情况是否总是如此。)

从以下评论中添加:

lldb中为其选择堆栈框架objc_exception_throw,然后输入以下命令:

(lldb) po *(id *)($esp + 4)

6
如何在lldb中做到这一点?我收到一个错误“错误:对“ id”的引用不明确”
offex 2012年

2
您可以提供此信息的来源吗?我想了解更多关于它
若奥·努涅斯

3
目前,在LLDBobjc_exception_throw 展开序幕前,以下对我有用po *(id *)($esp + 4)
wbyoung

7
这工作了!但是,直到我选择了堆栈帧0它才起作用。(objc_exception_throw)。
funroll

7
po $eax在模拟器中为我工作,作为$r0设备上的when挂件。
monkeydom

10

在例外框架中使用的新模拟器(iOS 8、64位)xcode 6 im上: objc_exception_throw

po $rax

在32位元中:

po $eax

什么是rax?

Rax是一个64位寄存器,替代了旧的eax

如何找到所有寄存器?

register read

来源维基百科


嗯...在Xcode 6.1中,我得到:(lldb)po $ rax错误:无法实现:无法读取rax寄存器的值在Execute中
出错

@bradheintz模拟器或设备?我想这与6.0.1
若奥·努涅斯

您可以为此提供指向您的来源的链接吗?谢谢!
克里斯·康诺夫

我只是在lldb中写了:register read。然后,利用此信息,我们知道异常帧中的第一个寄存器保存异常消息。
若奥·努涅斯

确定我发现了一些文档:RAX是一个64位寄存器:在64位长的模式下可以使用的64位寄存器(例如RAX代替EAX,RBX代替EBX,等等。)
若昂Nunes的

6

在撰写本文时,这篇文章是我在Google上获得的最高评价:lldb print exception。因此,我将此答案添加到lldb和x86_64帐户中。

我尝试使用查找异常,但po $eax失败了error: Couldn't materialize struct: Couldn't read eax (materialize)。链接文档中较早答案中描述的其他尝试也失败了。

关键是我必须首先单击objc_exception_throw主线程中的框架。lldb不在该帧中开始。

在我所有的搜索和以下示例中,此博客条目都是第一种以对我有用的方式来解释问题的文章。它更现代,将于2012年8月发布。


1

如果有catch语句,请在其中放置一个断点,然后可以在该点检查异常对象。

如果没有catch语句,请继续。

您将在终端中收到如下消息:

由于未捕获的异常'NSInvalidArgumentException'而终止应用程序,原因:' * -[__ NSPlaceholderDictionary initWithObjects:forKeys:count:]:尝试从对象[0]中插入零对象

但是,您可能正在寻找一种无需继续检查就可以对其进行检查的方法,因为当应用程序终止时,您将丢失漂亮的堆栈跟踪。

为此,听起来弗诺德的答案是最好的,但我无法使其在LLDB中正常工作。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.