前言
在iOS开发中经常使用NSLog进行打印调试,简单方便。NSLog每次调用会打印大量信息,时间、名称、进程等信息,多次调用打印会消耗资源,程序变慢效率低下,每次调试完毕要及时清理NSLog。 另外,每次想要NSLog打印看到信息,需要重新编译运行,对于较大的项目费时费力,所以调试最好使用调试器,LLDB调试器功能强大,由于能力有限只能简单介绍一下LLDB调试器的皮毛。
LLDB
LLDB是新一代高性能调试器,是Xcode上的默认调试器,支持调试C,Objective-C和C ++。LLDB命令结构有统一的格式。
LLDB命令结构
<noun>命令、<verb>命令操作、options命令选项、argument参数。命令各个元素之间用空格隔开,如果参数之中有空格则需要加上双引号。如果参数中带有反斜杠和双引号,则需要在其前面加上反斜杠。
options命令选项可以放在命令行的任何地方,但是如果argument参数以“-”开头,那么必须在option后面添加“--”结束标志进行区分,从而确定option的正确位置。例如你想启动一程序,“process launch”命令的option为“--stop-at-entry”,同时希望命令的argument为“-program_arg value”,你应该输入的命令为:
(lldb) process launch --stop-at-entry -- -program_arg value
help,它会列举出所有的命令。可以通过 help <command> 来了解更多细节,例 help print、help thread
详细的LLDB命令可以参考 LLDB command examples 命令总览。
在Xcode中使用LLDB调试程序
从Xcode 5开始LLDB成为了Xcode的默认调试器。LLDB提供了Xcode的底层调试环境,调试区域中的控制台窗口,用于在Xcode IDE环境中直接调用LLDB命令。
print(简写 p)打印值。
(lldb) p number (NSInteger) $0 = 1
可以给 print 指定不同的打印格式 print/<fmt>
(lldb) p/x number (NSInteger) $1 = 0x0000000000000001
16进制 p/x ,二进制(t=two) p/t , 打印字符 p/c , 打印以\0终止的字符串 p/s 。查看所有格式expression(简写 e)可改变程序中的值。
(lldb) e string = @“xxx.png”
输入 help print,可看到 'print' is an abbreviation for 'expression --'. (“print”是 “expression --”的缩写)po 打印对象
(lldb) po string
可以看到到对象的 description 方法的结果。和命令 (lldb) e -O -- string一个效果,e -o -- 的别名就是 po (print object 的缩写)。image
(lldb) image list
可以查看工程中使用到的库信息
(lldb) image lookup --address 0x0000000107c3f7d4
查找文件的原始地址
在命令行中使用LLDB调试程序
Xcode IDE通过将LLDB完全集成到源编辑,构建和使用图形控件的“运行调试”循环,自动化了许多这些操作。 从命令行了解这些操作如何工作有助于在Xcode控制台窗口中理解和使用LLDB调试器的功能。
加载程序到LLDB中
首先要创建一个程序用来调试。打开终端输入命令进入lldb,载入程序。
$ lldb (lldb) file /Users/Developer/Xcode/Build/Products/Test.app
或者直接载入
$ lldb /Users/Developer/Xcode/Build/Products/Test.app Current executable set to '/Users/Developer/Xcode/Build/Products/Test.appp' (x86_64).
启动程序
(lldb) process launch (lldb) run (lldb) r
可以使用进程ID或进程名来连接一个已经运行的程序,--waitfor选项告诉LLDB等待下一个名称为指定名称的程序出现,然后连接它。
(lldb) process attach --pid 123 (lldb) process attach --name Sketch (lldb) process attach --name Sketch --waitfor
breakpoint 设置断点
(lldb) breakpoint set --file main.m --line 12 (lldb) breakpoint set -f main.m -l 12
在函数名为foo处设置断点:
(lldb) breakpoint set --name foo (lldb) breakpoint set -n foo (lldb) breakpoint set --name foo --name bar
在C++中给所有命名为foo的方法设置断点
(lldb) breakpoint set --method foo (lldb) breakpoint set -M foo
在OC中给选择器名为alignLeftEdges:的设置断点
(lldb) breakpoint set --selector alignLeftEdges: (lldb) breakpoint set -S alignLeftEdges:
也可以写成:
(lldb) breakpoint set -n "-[SKTGraphicView alignLeftEdges:]" (lldb) br s -n "-[SKTGraphicView alignLeftEdges:]"
将断点限定在一个特定的可执行库中
(lldb) breakpoint set --shlib foo.dylib --n foo
设置别名
如果觉得命令行太麻烦可以自定义简单的名称,例如:
(lldb) command alias bfl breakpoint set -f %1 -l %2 (lldb) bfl foo.c 12
出去已创建的别名命令
(lldb) command unalias bfl
控制程序
(lldb) thread continue (lldb) thread step-in (lldb) thread step-over (lldb) thread step-out
查看线程状态
(lldb) thread list
总结
LLDB功能强大,可以做的事情很多,这里只是简单的整理了一下常用的命令,还有许多调试技巧等待着我们去发现,这么强大的调试器是值得我们花费时间和精力去深入研究的,熟练掌握调试技能会极大的提高工作效率。
References
http://lldb.llvm.org/tutorial.html
https://www.objc.io/issues/19-debugging/lldb-debugging/
https://developer.apple.com/library/content/documentation/IDEs/Conceptual/gdb_to_lldb_transition_guide/document/Introduction.html#//apple_ref/doc/uid/TP40012917-CH1-SW1