我是lldb的新手并尝试使用po [$eax class]
UI中显示的错误是:
Thread 1: EXC_BREAKPOINT (code=EXC_i386_BPT, subcode=0x0)
这是lldb控制台,包括我输入的内容和返回的内容:
(lldb) po [$eax class]
error: Execution was interrupted, reason: EXC_BAD_ACCESS (code=1, address=0xb06b9940).
The process has been returned to the state before expression evaluation.
全局断点状态切换已关闭。
答案 0 :(得分:5)
你的应用程序正在停止,因为你运行的代码引发了一个未被捕获的Mach异常。 Mach异常相当于Mach内核的BSD信号 - 它构成了macOS操作系统的最低级别。
在这种情况下,特定的Mach异常为EXC_BREAKPOINT
。 EXC_BREAKPOINT
是混淆的常见原因......因为它有"断点"在名称中人们认为它是一个调试器断点。这并非完全错误,但例外情况比这更普遍。
EXC_BREAKPOINT
实际上是Mach的较低层在执行某个指令(陷阱指令)时报告的例外情况。 lldb使用该陷阱指令来实现断点,但它也可以在各种系统软件中用作assert
的替代。例如,如果您访问数组的末尾,则swift会使用此错误。这是一种在错误点停止程序的方法。如果您在调试器外运行,则会导致崩溃。但是如果您在调试器中运行,那么控件将以EXC_BREAKPOINT
停止原因返回到调试器。
为避免混淆,如果陷阱是lldb插入到正在调试的程序中以实现调试器断点,则lldb永远不会向您显示EXC_BREAKPOINT
作为停止原因。它总是会说breakpoint n.n
。
因此,如果您看到一个以EXC_BREAKPOINT
作为停止原因而停止的线程,则意味着您已经遇到某种致命错误,通常是在您的程序使用的某些系统库中。此时的回溯将显示哪个组件引发了该错误。
无论如何,然后遇到了这个错误,你试图通过运行po [$eax class]
来调用eax寄存器中的类方法来找出它的类。调用该方法(这将导致代码在您正在调试的程序中运行)导致崩溃。这是"错误"你引用的消息告诉你。
这几乎肯定是因为$eax
没有指向有效的ObjC对象,所以你只是在某个随机值上调用一个方法,然后崩溃了
注意,如果你正在调试一个64位程序,那么$ eax实际上是真实参数传递寄存器的低32位 - $ rax。 64位指针的低32位不太可能是有效的指针值,因此调用class
导致崩溃并不奇怪。
如果你试图在64位Intel的第一个传递的参数(在ObjC方法中自我)上调用类,你真的想做:
(lldb) po [$rax class]
请注意,这也不太可行,因为$rax
仅在函数开头持有self
。然后它被用作临时寄存器。因此,如果您进入该函数的任何方式(事实上您的代码致命失败,某些测试看起来很可能),$ rax将不太可能仍然保持self
。
另请注意,如果这是一个32位程序,那么$eax
实际上并不用于参数传递 - 32位Intel代码在堆栈上传递参数,而不是寄存器。
无论如何,要弄清楚出错的第一件事就是在遇到此异常时打印回溯,并查看在发生此错误时运行的代码。
答案 1 :(得分:0)
我正在添加自己的解决方案,因为我一直在同一个问题中挣扎,却在任何地方都找不到此解决方案。
就我而言,我必须运行“产品”->“清理构建文件夹”(“清理+选项”键)并重建我的项目。断点和lldb命令开始正常工作。
答案 2 :(得分:0)
清理项目并重新启动Xcode对我有用。