(转)Xcode关于LLDB的使用
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了(转)Xcode关于LLDB的使用相关的知识,希望对你有一定的参考价值。
本文转自: http://www.dreamingwish.com/article/lldb-usage-a.html
LLDB是个开源的内置于XCode的具有REPL(read-eval-print-loop)特征的Debugger,其可以安装C++或者Python插件。
本系列针对于已经知道何为debugger,且有gdb或者lldb使用经验的读者。对于lldb的娴熟使用者,也可以用来作为查阅手册。
这一篇,我们讲述lldb内建的命令。
lldb与gdb命令名的对照表:http://lldb.llvm.org/lldb-gdb.html
1.help命令
单单执行help命令会列出所有命令列表,用户加载的插件一般来说列在最后。
执行help 可以打印指定command的帮助信息,至于插件提供的命令,其帮助信息取决于插件本身的实现。
例如 help print会打印内建命令print的使用帮助。
2.print命令
print命令的简化方式有prin pri p,唯独pr不能用来作为检查,因为会和process混淆,幸运的是p被lldb实现为特指print。
实际上你会发现,lldb对于命令的简称,是头部匹配方式,只要不混淆,你可以随意简称某个命令。
例如:
值得说明的是,返回的$0是命令结果的引用名,使用$0可以进行print $0 + 7这样打印出106,当然,$0可以被用于任何其他表达式或者接收参数的命令。
3.expression命令
expression命令可以用来修改变量的值,当然大部分情况下,使用xcode提供的可视化编辑器更方便。
1
2
3
4
|
(lldb) p count (NSUInteger) $4 = 12 (lldb)e count = 42 (NSUInteger) $5 = 42 |
实际上print相当于expression --,而--的意思是命令的参数终止,跟在--后面的都是命令的输入数据。
要打印一个对象,则需要使用e -O -- anObj,而e -O -- 的缩写正是我们常用的po命令:
1
2
3
4
5
|
(lldb) po $8 ( foo, bar ) |
要按特定格式来打印一个变量则使用p/
命令:
1
2
3
4
5
6
7
8
|
(lldb) p 16
16
(lldb)p/x 16
0x10
(lldb) p/t 16
0b00000000000000000000000000010000
(lldb) p/t ( char )16
0b00010000
|
或者使用p/c打印字符,p/s打印c字符串,详细格式查阅这里。
既然我们已经知道print实际上是expression --的简写,那么在p(或者po)后面跟上复杂的表达式则可以先计算表达式再打印最后的计算结果。
1
2
3
4
5
6
7
8
9
10
11
|
(lldb) e int $a = 2
(lldb) p $a * 19
38
(lldb) e NSArray *$array = @[ @ "Saturday" , @ "Sunday" , @ "Monday" ]
(lldb) p [$array count]
3
(lldb) po [[$array objectAtIndex:0] uppercaseString]
SATURDAY
(lldb) p [[$array objectAtIndex:$a] characterAtIndex:0]
error: no known method ‘-characterAtIndex:‘ ; cast the message send to the method‘s return type
error: 1 errors parsing expression
|
值得注意的是,一旦出现了上述错误提示,说明lldb无法判定某一步的计算结果是什么数据类型,这时需要强制类型转换来告诉lldb:
1
2
3
4
|
(lldb) p ( char )[[$array objectAtIndex :$a] characterAtIndex : 0 ]
‘M‘
(lldb) p/d ( char )[[$array objectAtIndex :$a] characterAtIndex : 0 ]
77
|
4.流程控制命令
实际上使用xcode自带的可视化工具来控制“继续”“暂停”“下一步”“进入”“跳出”更简单,但这里还是列出其所对应的命令名:
继续:process continue, continue, c
下一步:thread step-over, next, n
进入:thread step-in, step, s
跳出:thread step-out, finish, f
5.thread return命令
执行thread return命令可以使得当前函数立即返回,也就是说,后续代码都不会执行了。当然执行此命令可能会使得arc的计数追踪出现错乱。
thread return命令需要一个参数来指明函数强制返回时的返回值。
6.断点命令
一般来说,在xcode中新建/删除“行断点”是很容易的,但是断点还有很多进阶使用方法:
条件断点、条件执行、记录日志、自动继续、重复断点跳过。
使用xcode提供的可视化工具来操作是很容易的:
7.在debugger中执行任意代码
1
2
3
4
5
6
7
|
(lldb) e char *$str = ( char *)malloc( 128 )
(lldb) e ( void )strcpy($str, "wxrld of warcraft" )
(lldb) e $str[ 1 ] = ‘o‘
( char ) $ 0 = ‘o‘
(lldb) p $str
( char *) $str = 0x00007fd04a900040 "world of warcraft"
(lldb) e ( void )free($str)
|
所以,在debugger中可以修改view的颜色、尺寸、甚至创建controller来push。
8.watchpoint
watchpoint可以在某个变量被写入/读取时暂停程序运行:
1
2
3
4
5
6
7
8
9
10
11
|
(lldb) watchpoint set expression -- ( int *)&_abc4
Watchpoint created : Watchpoint 7 : addr = 0x15e36d3c size = 4 state = enabled type = w
new value : 0x00000000
(lldb) watchpoint set v -w read _abc4
Watchpoint created : Watchpoint 8 : addr = 0x15e36d3c size = 4 state = enabled type = r
watchpoint spec = ‘_abc4‘
new value : 0
(lldb) watchpoint set v -w read_write _abc3
Watchpoint created : Watchpoint 9 : addr = 0x15e36d38 size = 4 state = enabled type = rw
watchpoint spec = ‘_abc3‘
new value : 0
|
实际上可以使用watchpoint来监视任意一段内存的读写。
使用XCode也可以方便地创建watchpoint。
XCode的可视化debug工具中的watch是一个write类型watchpoint(也就是默认的)
另外,上述语句中 v是variable的简写,同样的,set可以简写为s,watch可以简写为wa,而-w后面的参数是不可以简写的必须为read、write或者read_write。
当前在arm和x86上,我们一次最多创建4个watchpoint,继续创建会提示错误。
9.符号断点
用xcode的可视化工具创建符号断点很简单,在Add symbolic breakpoint中填入符号名即可,这里给出objective-c的函数符号断点的写法:
1
2
|
-[MyViewController viewDidAppear :]
+[MyViewController sharedInstance ]
|
10.查看内存
使用XCode的可视化工具来查看memory,要注意watch memory of "p" 和watch memory of "*p"的区别。
手动执行命令可以help x或者 help memory。
小结
lldb的用法很灵活多样,但是XCode的可视化调试工具覆盖面有限,一些高级用法仍需手动输入命令,甚至结合python脚本。
转自: http://blog.sina.com.cn/s/blog_6dce99b10101gwwo.html
po(print object)是LLDB的一个命令,其主要功能是输出objective-c中对象(objects)的信息,与之相似的另外一个命令是 p(print),其主要功能是输出原生类型(boolean、integer、float、etc)的信息。
实用技巧一: 运行时修改变量的值
使用expr命令即可在运行时修改变量的值。
实用技巧二: 设置断点触发条件
断点的另外一个重要作用,是可以设置触发断点生效的条件,这样我们就可以在运行时针对特定的数据进行分析,观察app是否运行在正确的轨道上。如下图:
上述截图可以看到如下语句
1 |
( BOOL )[(NSString*)[item valueForKey:@ "ID" ] isEqualToString:@ "93306" ] |
通过这行语句,我们告诉编译器:当item中ID等于93306时,此断点生效,进入断点调试模式。
实用技巧三: 格式化输出数据
如果你厌倦了代码里无穷无尽的NSLog,幸运的是我们可以在编辑断点使其输出格式化字符串就像平常编码时一样。不过有一点需要注意,平常编码时可能会使用NSString‘s stringWithFormat:输出格式化字符串,不过这个方法貌似在断点中木有效果,你需要使用alloc/init形式的方法,如下:
1 |
po [[NSString alloc] initWithFormat:@ "Item index is: %d" , index] |
运行app,就能在控制台看到想要的输出啦!
简单!强大!这就是LLDB给你的选择,从此代码里可以不用再有NSLog满天飞的情况了,代码变得更干净了,心情变得更愉悦了!
LLDB还有很多强大的地方,本教程只不过揭开了它的面纱,即便如此,仍让我们沉醉不已。
以上是关于(转)Xcode关于LLDB的使用的主要内容,如果未能解决你的问题,请参考以下文章