前言 LLDB是我们平时调试中使用最多的工具之一,
p
或者po
是使用最多的指令。除了p
和po
之外,还有什么指令可以使用呢?今天再次来提升一下对LLDB的使用吧。
LLDB是个开源的内置于XCode的具有REPL(read-eval-print-loop)特征的Debugger,其可以安装C++或者Python插件。在日常的开发和调试过程中给开发人员带来了非常多的帮助。
断点删除
设置好断点后怎么控制前进、下一步呢? Xcode已经为我们提供了可视化的工具,但是如果你习惯了命令行操作不希望双手离开键盘降低你的效率,了解一下也是很有帮助的。
流程控制可视化界面
我们知道,用LLDB debug,大多数时候需要让程序stop。
target stop-hook
命令就是让你可以在每次stop的时候去执行一些命令
target stop-hook
只对breakpoint和watchpoint的程序stop生效,直接点击Xcode上的pause或者debug view hierarchy不会生效
假如我们想在每次程序stop的时候,都用命令打印当前view。我们可以添加一个stop-hook:
target stop-hook add
表示添加stop-hook,-o的全称是--one-liner,表示添加一条命令。
在程序stop的时候,他会自动执行frame variable
,打印出了所有的变量。
e.g: 下面2行代码效果相同
当添加完stop-hook之后,我们想看当前所有的stop-hook怎么办呢?使用stop-hook list
我们可以看到,我们添加了4个stop-hook,每个stop-hook都有一个id,他们分别是4,5,6
有添加的命令,当然也就有删除的命令。使用target stop-hook delete可以删除stop-hook,如果你觉得这个命令有点长,懒得敲。你也可以用undisplay
我们用target stop-hook delete和undisplay分别删除了id为4和5的stop-hook
当我们暂时想让某个stop-hook失效的时候,可以使用target stop-hook disable
如果我们想让所有的stop-hook失效,只需不传入stop-hookid即可:
有disable就有enable,我们又想让stop-hook生效了。可以使用target stop-hook enable
同理,不传入参数表示让所有stop-hook生效
五、image
当我们有一个地址,想查找这个地址具体对应的文件位置,可以使用image lookup --address,简写为image lookup -a e.g: 当我们发生一个crash。
我们可以看到是由于-[__NSArray0 objectAtIndex:]:超出边界而导致的crash,但是objectAtIndex:的代码到底在哪儿呢?
根据0x000000010a1c3e36 -[ViewController viewDidLoad]里面的地址,使用image lookup -address查找,我们可以看到代码位置在ViewController.m里面的32行。
(lldb) image lookup -t "method name"
来定位方法位置。
可以看到LLDB定位到test1在第25行 通过以上的命令完全可以看不出image到底是干嘛的!? 所以暂时只能记得其拥有特殊功效。
register
指令能够获取和修改各个寄存器的信息。
官方的解释是这样的:
我们可以通过register read
来获取当前断点中寄存器中的内容:
具体怎么用我还没学到?。见谅见谅
expression
命令是执行一个表达式,并将表达式返回的结果输出,是LLDB调试命令中最重要的命令,也是我们常用的p
和 po
命令的 鼻祖。
他主要有2个功能:
p
print
e
call
po
其实都是expression的别名,甚至我们还可以自己设置别名。这里不展开描述了。
frame 框架的意思,但它应解释成(帧)它能显示堆栈信息, 我们在控制台上输入命令bt,可以打印出来所有的frame。如果仔细观察,这些frame和左边红框里的堆栈是一致的。平时我们看到的左边的堆栈就是frame。
image.png
平时Debug的时候我们经常做的事就是查看变量的值,通过frame variable命令,可以打印出当前frame的所有变量
可以看到,他将self,_cmd,ret,a等本地变量都打印了出来 如果我们要需要打印指定变量,也可以给frame variable传入参数:
不过frame variable只接受变量作为参数,不接受表达式,也就是说我们无法使用frame variable self.string,因为self.string是调用string的getter方法。所以一般打印指定变量,我更喜欢用p或者po。
frame info: 查看当前frame的信息
frame select: 选择某个frame
当我们选择frame 1的时候,他会把frame1的信息和代码打印出来。不过一般我都是直接在Xcode左边点击某个frame,这样更方便
breakpoint有一个孪生兄弟watchpoint。如果说breakpoint是对方法生效的断点,watchpoint就是对地址生效的断点。 官方解释:
如果我们想要知道某个属性什么时候被篡改了,我们该怎么办呢?有人可能会说对setter方法打个断点不就行了么?但是如果更改的时候没调用setter方法呢? 这时候最好的办法就是用watchpoint。我们可以用他观察这个属性的地址。如果地址里面的东西改变了,就让程序中断。
watchpoint set命令用于添加一个watchpoint。只要这个地址中的内容变化了,程序就会中断。
watchpoint set variable传入的是变量名。需要注意的是,这里不接受方法。
设置成功后可以通过watchpoint list
可以查看到所有被标记的watchpoint。
当我执行p array = @[@"a",@"b"]
修改array后,watchpoint打印出了我旧值和新值。
除了以上指令之外,watchpoint当然也有和breakpoint一样的指令。 例如:
watchpoint disable
watchpoint enable
watchpoint delete
有时候我们想要了解线程堆栈信息,可以使用thread backtrace
thread backtrace
作用是将线程的堆栈打印出来。
e.g: 当发生crash的时候,我们可以使用thread backtrace
(线程回溯)查看堆栈调用 。
bt
则是 backtrace 的缩写,输入bt
等同于thread backtrace
线程回溯
Debug的时候,也许会因为各种原因,我们不想让代码执行某个方法,或者要直接返回一个想要的值。这时候就该thread return上场了 thread return可以接受一个表达式,调用命令之后直接从当前的frame返回表达式的值。
以上篇幅介绍的只是冰山一角。希望这篇文章能够给大家一些帮助,来更多的了解LLDB
作者:韩哒哒
感谢 韩哒哒 提供此原文给HelloCode 开发者学习平台.
人人为师,终身学习! 全栈开发从学习开始!
寒冬很冷,动动小手关注分享!
关注公众号,分享文章到朋友圈
作者:韩哒哒 链接:https://www.jianshu.com/p/995319aa8a41 來源:简书。
本公众号转载内容已尽可能注明出处,如未能核实来源或转发内容图片有权利瑕疵,请及时联系本公众号进行修改或者删除[联系方式QQ: 374487334 邮箱:374487334@qq.com].文章内容为作者独立观点,不代表本公众号立场.版本归原作者所有,如申请授权请联系作者,因文章侵权本公众号不承担任何法律以及连带责任.
本文分享自 HelloCode开发者学习平台 微信公众号,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文参与 腾讯云自媒体同步曝光计划 ,欢迎热爱写作的你一起参与!