LLDB调试基本使用

在平时开发中,我们可能需要调试某些东西,比如查看给服务器发请求时传过去的参数,如果不适用LLDB的话我们用的最多的就是通过NSLog方式去打印,但现在我们可以精简这个步骤,那就是使用LLDB调试命令.

Xcode从4.0开始编译器开始改用LLVM,相应的调试器也从gdb改为LLDB。而从 Xcode5.0开始所有工程也被自动设置为使用LLDB。

使用:

首先,我们需要先设置一个断点;

当程序执行到断电的时候就会弹出LLDB调试面板:

这个时候我们可以在这里输入对应命令行回车查看或更改参数

image

po 指令可以用来打印一些对象或者字符串

出了打印参数信息外,还可以动态更改属性值及其他功能,具体可以参照参考资料

print、p:打印

po:打印对象

e:修改变量的值

image

n:运行至下一行

c:运行至下个断点处(下面没有断点的话则继续运行程序)

call:调用。其实上述p/po后接表达式(expression)也有调用的功能,一般只在不需要显式输出,或是无返回值时使用call,用于动态调试插入调用代码。

例如可以在viewDidLoad:里面设置断点,然后在程序中断的时候输入以下命令:

call [self.view setBackgroundColor:[UIColor redColor]];

image:可用于寻址(这个命令和图片没有任何关系) 这个功能很强大了 比如我们经常项目出现crash 控制台上就会打印下面的信息 这个时候我们可以根据这个信息来准确找到闪退位置(虽然闪退原因头部写的很清楚了 但是假如这个文件有很多setValueForKey方法呢,我们一个个找起来太费劲 我们就可以通过image来准确定位)

image

首先我们在上面信息中查找我们运行的程序的内存地址:也就是第4个 KVODemo对应的内存地址 0x00000001089faf99

然后在LLDB控制器面板输入命令:image lookup --address 0x00000001089faf99 然后回车

就看到打印信息:

Address: KVODemo[0x0000000100001f99] (KVODemo.__TEXT.__text + 1113)
Summary: KVODemo`-[ViewController touchesBegan:withEvent:] + 265 at ViewController.m:126:5

Summary就会显示哪个文件多少行 在ViewController.m文件的126行

bt(backtrace),打印当前调用堆栈(crash堆栈),“bt all”可打印所有thread的堆栈(相当于command+6的Debug Session Navigation)。

首先介绍一下什么叫调用堆栈:假设我们有几个函数,分别是function1,function2,function3,funtion4,且function1调用function2,function2调用function3,function3调用function4。在function4运行过程中,我们可以从线程当前堆栈中了解到调用他的那几个函数分别是谁。把函数的顺序关系看,function4、function3、function2、function1呈现出一种“堆栈”的特征,最后被调用的函数出现在最上方。因此称呼这种关系为调用堆栈(call stack)。

2.  作用

“调用堆栈”窗口可以查看当前堆栈上的函数或过程调用。
“调用堆栈”窗口显示每个函数的名称和编写它所用的编程语言。函数或过程名可能伴随有可选信息,如模块名、行号、字节偏移量以及参数的名称、类型和值。 可以打开或关闭这些可选信息的显示。
一个黄色箭头标识执行指针当前所位于的堆栈帧。 默认情况下,该帧的信息显示在源、“反汇编”、“局部变量”、“监视”和“自动”窗口中。 如果想将上下文更改为堆栈上的另一个帧,可以在“调用堆栈”窗口中执行相应的操作。
当调试符号对部分调用堆栈不可用时,“调用堆栈”窗口也许就不能显示那部分堆栈的正确信息。
 

常用的场景:

当故障发生时,如果程序被中断,我们基本上只可以看到最后出错的函数。

利用调用堆栈,我们可以知道当出错函数被谁调用的时候出错。这样一层层的看上去,有时可以猜测出错误的原因。

读取对象的内存地址:memory red ↓↓ 关于内存地址和对象本质的问题在底层文章中有所介绍

memory read/数量格式字节数  读取对象/或某个具体的内存地址

(lldb) memory read/3xw ani
0x6000010893a0: 0x07ff3318 0x00000001 0x00000001

数量是指读取从该对象起始地址或该内存地址起始地址后多长的地址
格式
x是16进制,f是浮点,d是10进制

字节大小
b:byte 1字节,h:half word 2字节
w:word 4字节,g:giant word 8字节
image

修改内存中的值
memory write 内存地址 数值↓↓↓

当我们读取到对象的地址值是 就可以动态修改内存地址所指向数据的值 比如上图中age属性的地址值是**0x6000010893a8开始后的四个字节 **

(lldb)memory write 0x6000010893a8 5

我们再打印age的属性值时  就变成了5

(lldb) p ani.age
(int) $18 = 5
(lldb) 

这个值的修改是真实有效的 并不是只存在于lldb面板中 在程序中都是有效的

frame:(这个frame并不是用来设置布局的frma 而是[帧] 也就是我们通过bt命令打印出来的调用堆栈)用于选择和检查当前线程堆栈帧的命令。

frame variable
平时Debug的时候我们经常做的事就是查看变量的值,通过frame variable命令,可以打印出当前frame[也就是断点所在的方法]的所有变量

(lldb) frame variable
(ViewController *) self = 0x00007fc263c10930
(SEL) _cmd = "viewDidLoad"
(PersonClass *) person1 = 0x00006000012c8b10
(AnimalClass *) ani = 0x00006000010893a0
(PersonClass *) person2 = 0x00006000012cc4a0

frame info: 查看当前frame[当前断点所在的方法]的信息

(lldb) frame info
frame #0: 0x0000000107fefdfa KVODemo`-[ViewController viewDidLoad](self=0x00007fc263c10930, _cmd="viewDidLoad") at ViewController.m:32:20

frame select: 选择某个frame(不常用) 这里select 后面跟的数字就是通过bt打印出来的当前调用堆栈对应的frame数字

(lldb) frame select 1
frame #1: 0x000000010ba8f43b UIKitCore`-[UIViewController loadViewIfRequired] + 1183
UIKitCore`-[UIViewController loadViewIfRequired]:
->  0x10ba8f43b <+1183>: movl   (%r14), %eax
    0x10ba8f43e <+1186>: testl  %eax, %eax
    0x10ba8f440 <+1188>: je     0x10ba8f786               ; <+2026>
    0x10ba8f446 <+1194>: cmpl   $0x70000, %eax            ; imm = 0x70000

(lldb) frame select 8
frame #8: 0x0000000114ef86d6 UIKitCore`__111-[__UICanvasLifecycleMonitor_Compatability _scheduleFirstCommitForScene:transition:firstActivation:completion:]_block_invoke + 904
UIKitCore`__111-[__UICanvasLifecycleMonitor_Compatability _scheduleFirstCommitForScene:transition:firstActivation:completion:]_block_invoke:
->  0x114ef86d6 <+904>: movq   (%rbx), %rdi
    0x114ef86d9 <+907>: movq   0x1442aa8(%rip), %rsi     ; "_calledRunWithMainScene"
    0x114ef86e0 <+914>: callq  *%r14
    0x114ef86e3 <+917>: movq   %r12, %rdi
(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
    frame #0: 0x000000010f602d58 KVODemo`-[ViewController viewDidLoad](self=0x00007faca36083e0, _cmd="viewDidLoad") at ViewController.m:25:25
    frame #1: 0x00000001150b243b UIKitCore`-[UIViewController loadViewIfRequired] + 1183
    frame #2: 0x00000001150b2868 UIKitCore`-[UIViewController view] + 27
    frame #3: 0x00000001156eac33 UIKitCore`-[UIWindow addRootViewControllerViewIfPossible] + 122
    frame #4: 0x00000001156eb327 UIKitCore`-[UIWindow _setHidden:forced:] + 289
    frame #5: 0x00000001156fdf86 UIKitCore`-[UIWindow makeKeyAndVisible] + 42
    frame #6: 0x00000001156adf1c UIKitCore`-[UIApplication _callInitializationDelegatesForMainScene:transitionContext:] + 4555
    frame #7: 0x00000001156b30c6 UIKitCore`-[UIApplication _runWithMainScene:transitionContext:completion:] + 1617
  * frame #8: 0x0000000114ef86d6 UIKitCore`__111-[__UICanvasLifecycleMonitor_Compatability _scheduleFirstCommitForScene:transition:firstActivation:completion:]_block_invoke + 904
    frame #9: 0x0000000114f00fce UIKitCore`+[_UICanvas _enqueuePostSettingUpdateTransactionBlock:] + 153
    frame #10: 0x0000000114ef82ec UIKitCore`-[__UICanvasLifecycleMonitor_Compatability _scheduleFirstCommitForScene:transition:firstActivation:completion:] + 236
    frame #11: 0x0000000114ef8c48 UIKitCore`-[__UICanvasLifecycleMonitor_Compatability activateEventsOnly:withContext:completion:] + 1091
    frame #12: 0x0000000114ef6fba UIKitCore`__82-[_UIApplicationCanvas _transitionLifecycleStateWithTransitionContext:completion:]_block_invoke + 782
    frame #13: 0x0000000114ef6c71 UIKitCore`-[_UIApplicationCanvas _transitionLifecycleStateWithTransitionContext:completion:] + 433
    frame #14: 0x0000000114efb9b6 UIKitCore`__125-[_UICanvasLifecycleSettingsDiffAction performActionsForCanvas:withUpdatedScene:settingsDiff:fromSettings:transitionContext:]_block_invoke + 576
    frame #15: 0x0000000114efc610 UIKitCore`_performActionsWithDelayForTransitionContext + 100
    frame #16: 0x0000000114efb71d UIKitCore`-[_UICanvasLifecycleSettingsDiffAction performActionsForCanvas:withUpdatedScene:settingsDiff:fromSettings:transitionContext:] + 223
    frame #17: 0x0000000114f006d0 UIKitCore`-[_UICanvas scene:didUpdateWithDiff:transitionContext:completion:] + 392
    frame #18: 0x00000001156b19a8 UIKitCore`-[UIApplication workspace:didCreateScene:withTransitionContext:completion:] + 514
    frame #19: 0x0000000115268dfa UIKitCore`-[UIApplicationSceneClientAgent scene:didInitializeWithEvent:completion:] + 361
    frame #20: 0x000000011bf9f125 FrontBoardServices`-[FBSSceneImpl _didCreateWithTransitionContext:completion:] + 448
    frame #21: 0x000000011bfa8ed6 FrontBoardServices`__56-[FBSWorkspace client:handleCreateScene:withCompletion:]_block_invoke_2 + 283
    frame #22: 0x000000011bfa8700 FrontBoardServices`__40-[FBSWorkspace _performDelegateCallOut:]_block_invoke + 53
    frame #23: 0x00000001121a0db5 libdispatch.dylib`_dispatch_client_callout + 8
    frame #24: 0x00000001121a42ba libdispatch.dylib`_dispatch_block_invoke_direct + 300
    frame #25: 0x000000011bfda146 FrontBoardServices`__FBSSERIALQUEUE_IS_CALLING_OUT_TO_A_BLOCK__ + 30
    frame #26: 0x000000011bfd9dfe FrontBoardServices`-[FBSSerialQueue _performNext] + 451
    frame #27: 0x000000011bfda393 FrontBoardServices`-[FBSSerialQueue _performNextFromRunLoopSource] + 42
    frame #28: 0x000000011089dbe1 CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17
    frame #29: 0x000000011089d463 CoreFoundation`__CFRunLoopDoSources0 + 243
    frame #30: 0x0000000110897b1f CoreFoundation`__CFRunLoopRun + 1231
    frame #31: 0x0000000110897302 CoreFoundation`CFRunLoopRunSpecific + 626
    frame #32: 0x0000000118ef82fe GraphicsServices`GSEventRunModal + 65
    frame #33: 0x00000001156b4ba2 UIKitCore`UIApplicationMain + 140
    frame #34: 0x000000010f603440 KVODemo`main(argc=1, argv=0x00007ffee05fbf08) at main.m:14:16
    frame #35: 0x0000000112215541 libdyld.dylib`start + 1
    frame #36: 0x0000000112215541 libdyld.dylib`start + 1

watchpoint:观察变量或者属性 这是一个非常有用的东西,我们经常遇到,某一个变量,不知道什么时候值被改掉了,就可以使用这个东西去定位:

watchpoint set variable self->_person1->_age

//注意 不能使用点语法

设置成功后会打印↓↓

(lldb) watchpoint set variable self->_person1->_age
Watchpoint created: Watchpoint 1: addr = 0x600001dbc948 size = 4 state = enabled type = w
    watchpoint spec = 'self->_person1->_age'
    new value: 1

这样当self.person1.age的值发生改变时就对自动断点 打印一下信息↓↓

Watchpoint 1 hit:
old value: 1
new value: 123

这个时候我们可以在左侧调用堆栈中找到调用的方法

image

也可以继续在控制器敲入bt:查看当前调用堆栈 找到对应的方法↓↓

image

这里只是介绍一些常用的 我们也可以在lldb调试面板中通过help指令来学习更多的功能↓↓

image
image
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,383评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,522评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,852评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,621评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,741评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,929评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,076评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,803评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,265评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,582评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,716评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,395评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,039评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,027评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,488评论 2 361
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,612评论 2 350

推荐阅读更多精彩内容