LLDB调试入门

不多不少写了三四万行的iOS代码,但调试方法一直没怎么学习,最常用就用NSLog输出和打断点了,这在开发自己的项目时可能觉得还能接受,但在看别人的项目代码时就是一种折磨,那么现在来稍微学点LLDB调试技巧。

两个重要命令的使用

watchpoint

主要用于观察变量值的具体变化
比如需要观察某个变量x的值变化,可以使用以下命令

1
(lldb) watchpoint set variable a

成功添加watchpoint后结果如下

1
2
3
4
(lldb) watchpoint set variable _bookNameArray
Watchpoint created: Watchpoint 1: addr = 0x7fe61ba045f8 size = 8 state = enabled type = w
watchpoint spec = '_bookNameArray'
new value: 0x0000000000000000

用frame命令查看变量具体值

1
2
frame variable _bookNameArray
(NSMutableArray *) _bookNameArray = nil

设置变量变化为某个特定值后打印相关信息,下面设置对象不为空时触发

1
2
3
4
5
6
7
8
9
10
(lldb) watchpoint modify -c '(_bookNameArray!=nil)'
2017-02-17 16:44:14.357 PageBoy[2814:172446] 0x60800006a980
2017-02-17 16:44:14.358 PageBoy[2814:172446] 0x60000004dd10
2017-02-17 16:44:14.359 PageBoy[2814:172446] 书名:西厢记
2017-02-17 16:44:14.359 PageBoy[2814:200714] XPC connection interrupted
2017-02-17 16:44:14.360 PageBoy[2814:172446] _bookName的长度:1

Watchpoint 1 hit:
old value: 0x0000000000000000
new value: 0x000060000004dd10

image

快速定位错误代码
测试代码,数组越界

1
2
NSArray *arr=[[NSArray alloc] initWithObjects:@"1",@"2", nil];
NSLog(@"%@",arr[2]);

运行后报错

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[__NSArrayI objectAtIndex:]: index 2 beyond bounds [0 .. 1]'
*** First throw call stack:
(
0 CoreFoundation 0x00007fffab6b1e7b __exceptionPreprocess + 171
1 libobjc.A.dylib 0x00007fffc029bcad objc_exception_throw + 48
2 CoreFoundation 0x00007fffab5d474c -[__NSArrayI objectAtIndex:] + 156
3 test 0x0000000100000eb2 main + 146
4 libdyld.dylib 0x00007fffc0b7f255 start + 1
5 ??? 0x0000000000000001 0x0 + 1
)
```
除了test其它都是系统的库,利用image的lookup命令可以定位到代码所在文件的行数

```objc
(lldb) image lookup --address 0x0000000100000eb2
Address: test[0x0000000100000eb2] (test.__TEXT.__text + 146)
Summary: test`main + 146 at main.m:21

显示错误代码在main.m文件的第21行

简介

LLDB 是一个有着 REPL 的特性和 C++ ,Python 插件的开源调试器。LLDB 绑定在 Xcode 内部,存在于主窗口底部的控制台中。调试器允许你在程序运行的特定时暂停它,你可以查看变量的值,执行自定的指令,并且按照你所认为合适的步骤来操作程序的进展。

快捷键
为了方便调试,记着些快捷键还是有必要的

快捷键功能 命令
暂停/继续 cmd + ctrl + Y
控制台显示/隐藏 cmd + Y
光标切换到控制台 cmd + shift + C
清空控制台 cmd + K
step over、step into、step out F6、F7、F8

基本使用

LLDB控制台平时会输出一些log信息。如果我们想输入命令调试,必须让程序进入暂停状态。让程序进入暂停状态的方式主要有2种:

  • 断点或者watchpoint: 在代码中设置一个断点(watchpoint),当程序运行到断点位置的时候,会进入stop状态
  • 直接暂停,控制台上方有一个暂停按钮,上图红框已标出,点击即可暂停程序
    one

输入help就能看到各个命令使用帮助

命令使用

  • po

    • 执行某个表达式。我们在代码运行过程中,可以通过执行某个表达式来动态改变程序运行的轨迹。假如我们在运行过程中,突然想把 某个view颜色改成红色,看看效果。我们不必写下代码,重新run,只需暂停程序,用po改变颜色,让程序继续运行就能显示改变的 操作。
      two

    three

    • 查看对象信息
    1
    2
    	(lldb) po 0x7ff56f010600
    <UICollectionView: 0x7ff56f010600; frame = (0 34; 375 633); clipsToBounds = YES; autoresize = W+H; gestureRecognizers = <NSArray: 0x608000044440>; layer = <CALayer: 0x60000002d5a0>; contentOffset: {0, -20}; contentSize: {375, 186}> collection view layout: <UICollectionViewFlowLayout: 0x7ff56de009c0>

    lldb命令其实有很多,但直接用可能不太好用,接下来用facebook封装好的工具chisel

chisel的基本使用

安装

官方Github中可以找到安装方法

1
2
brew update
brew install chisel

Then follow the instructions that Homebrew displays to add chisel to your ~/.lldbinit.

Alternatively, download chisel and add the following line to your ~/.lldbinit file. If it doesn’t exist, create it.

# ~/.lldbinit

command script import /path/to/fblldb.py
The commands will be available the next time Xcode starts.

大体就是就用homebrew安装,安装完后有提示加入command script import /path/to/fblldb.py这句句命令到/.lldbint,其中path在安装完后会有提示,如果没有/.lldbint这个文件就创建一个。
常用命令在github上已经大概给出了,翻译记录一下吧

  • pviews
    递归打印一个view的层级结构
  • pvc
    递归打印一个控制器的层级结构
  • visualize
    直接用mac上的软件预览UIImage, CGImageRef, UIView, CALayer, NSData (of an image), UIColor, CIColor, or CGColorRef
  • show/hide
    显示或隐藏一个view
  • border/unborder
    给一个view添加或去掉边框,主要用来标记一个view border 0x7ff56df1eb20 -c blue -w 3
  • mask/unmask
    用一个半透明的矩形覆view盖一个view,网上说有bug,我使用正常,当然,这样一来被覆盖的view是不能交互的mask 0x7ff56df1eb20 -c blue -a 0.5
  • bmessage
    这玩意是打断点用的,当想在那些没有实现viewWillAppear方法又想观察view将出现的内存情况时可以执行bmessage -[MyViewController viewWillAppear:]
  • presponder
    查看响应者链条
  • pclass
    查看对象的继承关系