还记得几个月前写「 iOS调试技巧(1)——断点」的时候,GDBLLDB还是一对好基友,Xcode里可以随意切换。按照苹果的风(niao)格(xing),自家的LLVM居然能和GCC和谐共处,实属难得。所以,刚刚发布的Xcode 5 阉割掉GCC之后,群众纷纷表示情绪稳定,见怪不怪。对于那些习惯了GDB的老程序猿的骂娘行为,苹果表示:我就是把GCC干掉,你打我啊!

吐槽完毕,进入正题。

基本操作

指令 作用
c continue,进程继续运行
r run,进程重新运行
kill run,kill进程
s step-in
n step-over
finish step-out

断点

指令 作用
b 打印所有断点
b-[NSString stringWithFormat:] Objective-C函数断点
b objc_msgSend C/C++函数断点
b resignFirstResponder 对所有含有resignFirstResponder的函数进行断点
br del 1 删除某个断点(标号可以通过「打印所有断点」取得

堆栈

指令 作用
bt 打印当前线程堆栈
bt all 打印所有线程堆栈
up 跳到上一个调用栈
down 跳到下一个调用栈

p 和 po

p指令可以打印结构体以及基本类型,有时会出现异常,尝试类型强转,如 p (int)a 。

除了p指令外,LLDB增加了po,如 po self ,用来打印一个OC对象的description。

又如下面这句:

1
po [[[UIApplication sharedApplication] keyWindow] recursiveDescription]

可以用来打印一个UIView的层次结构。在Reveal还没有出来之前,这个方法是用来快速查看UIView的层次结构。

事实上,p 和 po 指令是用来执行代码,并输出返回值结果。用来打印输出只是返回结果罢了。所以,在断点处输入

1
po [self.view setBackgroundColor:[UIColor whiteColor]]

是可以实时生效的。

image

image指令可以操作符号相关的东西。

1
2
NSArray *array = [[NSArray alloc] init];
NSObject *i = [array objectAtIndex:0];

比如说上面的代码,运行时崩溃,控制台会输入如下:

通过控制台输出,可以猜测崩溃在我们的程序「test」中的某处(上图标红处),此时通过指令

1
image lookup −a 0x00000001036d58e7

可以看出,程序崩溃在ViewController.m的第38行。

另外,还有一个非常好用的指令,可以用来打印和某关键字相关的符号,如下:

1
image lookup −r −n UIWebView

参考

The LLDB Debugger