iOS 底层 day 10 LLDB 指令
2020-08-02 本文已影响0人
望穿秋水小作坊
一、需要掌握的常用指令
-
help
忘记是每个人的本性,通过 help 指令可以列出指令的用法。
(lldb) help p
Syntax: p <expr>
Command Options Usage:
p <expr>
'p' is an abbreviation for 'expression --'
-
p <expression>
通过help p
我们获得说明'p' is an abbreviation for 'expression --'
即p
是expression
的简写
- 用于执行一个表达式,可以为断点的程序添加一个额外的代码。
(lldb) p self.view.backgroundColor = [UIColor yellowColor];
(UICachedDeviceRGBColor *) $0 = 0x00006000020dafc0
解析:上述修改 view 背景的代码源代码中是不存在,但是我们过掉断点后,view 就会被修改成黄色。这个功能在我们深入调试某个程序,并且想修改代码一些逻辑的时候非常好用。
- 用于打印一个对象的地址
(lldb) p self.view
(UIView *) $1 = 0x00007f80104101a0
解析:仅用于打印对象的类型和地址值,思考和 po self.view
的区别?
-
break set -n <functionName>
通过命令行给指定方法添加断点
- 给
ViewController
类中的touchesBegan:withEvent:
方法添加断点。如果没有添加类别说明,那么会给 iOS 项目中所有touchesBegan:withEvent:
方法添加断点。
(lldb) breakpoint set -n "[ViewController touchesBegan:withEvent:]"
Breakpoint 3: where = LLDBTest`-[ViewController touchesBegan:withEvent:]
+ 77 at ViewController.m:25:5, address = 0x00000001022b3edd
-
bt
是thread backtrace
的简称,用于打印栈帧
,帮助我们观察方法调用栈。
(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 2.1
* frame #0: 0x0000000106d55eec LLDBTest`-[ViewController test](self=0x00007f9e00e054f0, _cmd="test") at ViewController.m:32:9
frame #1: 0x0000000106d55e8b LLDBTest`-[ViewController touchesBegan:withEvent:](self=0x00007f9e00e054f0, _cmd="touchesBegan:withEvent:", touches=1 element, event=0x0000600002d0c640) at ViewController.m:26:5
frame #2: 0x00007fff4718f0bf UIKitCore`forwardTouchMethod + 340
frame #3: 0x00007fff4718ef5a UIKitCore`-[UIResponder touchesBegan:withEvent:] + 49
frame #4: 0x00007fff4719df3e UIKitCore`-[UIWindow _sendTouchesForEvent:] + 1867
frame #5: 0x00007fff4719fb26 UIKitCore`-[UIWindow sendEvent:] + 4596
frame #6: 0x00007fff4717b1a7 UIKitCore`-[UIApplication sendEvent:] + 356
frame #7: 0x00007fff471faa18 UIKitCore`__dispatchPreprocessedEventFromEventQueue + 6847
frame #8: 0x00007fff471fd4de UIKitCore`__handleEventQueueInternal + 5980
frame #9: 0x00007fff23afbac1 CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17
frame #10: 0x00007fff23afb9ec CoreFoundation`__CFRunLoopDoSource0 + 76
frame #11: 0x00007fff23afb1c4 CoreFoundation`__CFRunLoopDoSources0 + 180
frame #12: 0x00007fff23af5ecf CoreFoundation`__CFRunLoopRun + 1263
frame #13: 0x00007fff23af56b6 CoreFoundation`CFRunLoopRunSpecific + 438
frame #14: 0x00007fff3815cbb0 GraphicsServices`GSEventRunModal + 65
frame #15: 0x00007fff47162a67 UIKitCore`UIApplicationMain + 1621
frame #16: 0x0000000106d561e4 LLDBTest`main(argc=1, argv=0x00007ffee8ea8d28) at main.m:18:12
frame #17: 0x00007fff5123bcf5 libdyld.dylib`start + 1
frame #18: 0x00007fff5123bcf5 libdyld.dylib`start + 1
-
frame variable
用于打印断点所在方法内所有局部变量的值
(lldb) frame variable
(ViewController *) self = 0x00007f9e00e054f0
(SEL) _cmd = "test"
(int) a = 1072693248
(int) b = 0
- 控制断点走向的指令
thread continue
、continue
、c
:程序继续运行
thread step-over
、next
、n
:单步运行,把自海曙当做整体一步执行
thread step-in
、step
、s
: 单步运行,遇到子函数会进入子函数
thread step-out
、finish
:直接执行完当前函数的所有代码,返回到上一个函数
si
、ni
和s
、n
类似
- s 、n 是源码级别指令
- si、ni 是汇编级别指令
- 内存断点,在内存数据发生变化的时候触发,方便我们观察指定值什么时候改变。有点类似于复写了 set 方法,并且在 set 方法内部打断点。
watchpoint set variable 变量
(lldb) watchpoint set variable self->_age
Watchpoint created: Watchpoint 1: addr = 0x7ff5a2e037d0 size = 4 state = enabled type = w
watchpoint spec = 'self->_age'
new value: 0
- 触发修改 age 值的时候
Watchpoint 1 hit:
old value: 0
new value: 10