iOS调试笔记

最常见的做法是在 LLDB 使用 po [[UIWindow keyWindow] recursiveDescription] 来检查层次结构。它可以以文本形式打印出完整的视图层次结构。

po [[[UIWindow keyWindow] rootViewController] _printHierarchy]

https://github.com/facebook/chisel
LLDB 非常强大并且可以脚本化。 Facebook 发布了一组名为 Chisel 的 Python 脚本集合 为日常调试提供了非常多的帮助。pviews 和 pvc 等价于视图和视图控制器的层次打印。

bt
利用 LLDB 的 bt 命令,你可以打印断点。bt all 可以达到一样的效果,区别在于会打印全部线程的状态,而不仅是当前的线程。

我们知道每个 Objective-C 方法都有两个隐式参数:self 和 _cmd。于是我们所需要的就是在栈上的第一个对象。在 32-bit 架构中,栈信息保存在 $esp 里,所以在 Objective-C 方法中你可以你可以使用 po (int)($esp+4) 来获取 self,以及使用 p (SEL)(int)($esp+8) 来获取 _cmd。$esp 里的第一个值是返回地址。随后的变量保存在 $esp+12,$esp+16 以及依此类推的其他位置上。

x86-64 架构 (那些包含 arm64 芯片 iPhone 设备的模拟器) 提供了更多寄存器,所以变量放置在 $rdi,$rsi,$rdx,$rcx,$r8,$r9 中。所有后续的变量在 $rbp 栈上。开始于 $rbp+16,$rbp+24 等。

armv7 架构的变量通常放置在 $r0,$r1,$r2,$r3 中,接着移动到 $sp 栈上:

(lldb) po $r0
page:0>

(lldb) p (SEL)$r1
(SEL) $1 = "dismissViewControllerAnimated:completion:"
arm64 类似于 armv7,然而,因为有更多的寄存器,从 $x0 到 $x7 的整个范围都用来存放变量,之后回到栈寄存器 $sp 中。

构建软件是复杂的,并且 Bug 总会出现。一个常见的修复周期就是修改代码,编译,重新运行,并且祈祷出现最好的结果。

但是不一定要这么做。你可以使用调试器。而且即使你已经知道如何使用调试器检查变量,它可以做的还有很多。

help
最简单命令是 help,它会列举出所有的命令。如果你忘记了一个命令是做什么的,或者想知道更多的话,你可以通过 help 来了解更多细节,例如 help print 或者 help thread。如果你甚至忘记了 help 命令是做什么的,你可以试试 help help。不过你如果知道这么做,那就说明你大概还没有忘光这个命令

expression
如果想改变一个值怎么办?
这不仅会改变调试器中的值,实际上它改变了程序中的值。这时候继续执行程序,将会打印 42 red balloons。神奇吧。
注意,从现在开始,我们将会偷懒分别以 p 和 e 来代替 print 和 expression。

po
实际上,我们想看的是对象的 description 方法的结果。我么需要使用 -O (字母 O,而不是数字 0) 标志告诉 expression 命令以 对象 (Object) 的方式来打印结果。
幸运的是,e -o -- 有也有个别名,那就是 po (print object 的缩写),我们可以使用它来进行简化:

与调试器共舞

你可能感兴趣的:(iOS调试笔记)