运行,暂停,检查:探索如何使用LLDB进行有效调试
文章目录
- 常见的检查技巧
- 日志检查
- print检查
- LLDB
- 调试器工作流
- 回溯栈跟踪
- 断点
- 变量检查
针对程序问题进行调试,是每个编程的人都会做的
因为基本上没有天才可以一直写正确的代码
从写算法题目,到现在的仿写项目,我们都在用不同的方式来进行调试,修正代码中的问题
调试程序时,我们通常会知道程序出现错误的时间点,这之间的某个时间执行了错误的代码,我们的目标就是找到这段代码
我们通常可以通过检查不同时间点的程序状态来找到错误,每个检查都会让我们离错误更近一点
常见的检查技巧
日志检查
一些代码库会使用日志语句
在这种情况下,读取日志文件的某个条目
类似于检查程序中的某个时间点
如果日志足够详细,可能无需其他操作,就能精确找到代码中的错误,这种方法需要程序员有先见之明
即他能够确定哪些是需要记录的有用信息
但它也是一种在用户和开发者之间传输ap诊断信息的有效技巧
print检查
打印调试可能是我们所有人学习的第一种调试方法
利用打印调试,我们可以在程序中加入print语句,重新编译代码,运行程序并复现错误
最后检查打印出的信息
如果需要打印新的内容,就重复这个过程
但是不要忘记,在完成调试之后,要移除print语句
这整个过程可能非常耗时,并且容易出错
LLDB
LLDB 是 Xcode 附带的底层调试器,能够随时暂停你的程序,检查变量状态,计算表达式等等
接下来,我们来看看它能做什么

调试器工作流
在调试程序的时候,我们一直在重复三个不同的操作
- 运行程序
- 在需要关注的地方暂停
- 检查程序状态

高效地反复完成运行,暂停,检查这一循环
是实现有效调试回话的关键所在
调试问题的第一步是重现错误,即运行程序
不过LLDB可以提供这方面的帮助
在Apple平台上,每次发生程序崩溃后,系统都会收集程序崩溃时的状态信息,并创建崩溃日志
LLDB能读取崩溃日志,有时,我们可能只需要查看这份日志就能查明错误来源

例如这个崩溃日志,很显然API返回全为空,很显然是服务器无了
回溯栈跟踪
回溯栈跟踪描述了导致这个程序状态的函数调用序列,也成为栈帧,它可以让我们了解每个函数的作用
它可以让我们了解每个函数的作用,它们是在哪里被调用的,以及每个函数要返回到哪里

我们可以在 Xcode 的调试,导航器中找到当前的回溯栈跟踪

这里我们可以看到问题发生在VC的初始化阶段,并且下一个方法是[__NSArray0 objectAtIndex:] ()
判断出有可能是空数组访问导致的崩溃
无论是搭配崩溃日志使用吗还是在常规调试回话中使用,回溯栈跟踪都是了解程序控制流的强大工具
搭配崩溃日志使用时,回溯栈跟踪可帮助我们直观的了解崩溃是如何发生的
断点
断点的设置实际上非常简单,像其他编译器一样,我们只需要在想要中断的代码旁边点一下,就好了
Xcode会高亮断点的代码

更为高级一点的是符号断点
符号断点不需要你知道你的代码具体在哪一行,你只需要知道方法的名字即可
在Xcode的导航栏找到断点一栏(像书签一样的一个符号)
点击下方的+号
选择Symbolic Breakpoint…
在symbol一栏里填写你的方法名即可
注意!!!
这里的断点设置之后,所有名叫这个方法名的方法全会被停止

异常断点
Xcode编译器的风评相当差,很多评论其实都在说在程序崩溃之后,Xcode会给你停在main.m文件里
导致你根本不知道是哪里出问题
异常断点式解决这个的方法之一
它的作用就是在App即将因为一个未捕获的异常(比如数组越界或者给nil发送消息导致的崩溃)而闪退的前一刻,把程序暂停在出错的那一行
还是在刚刚的导航栏部分,点击+
选择 “Exception Breakpoint…”
Exception: 设置为 Objective-C
Break: 设置为 On Throw
好的这样程序就会在即将崩溃前暂停程序

可以看到我并没有加断点,程序在我即将访问空数组的时候自动帮我打上了断点并暂停在这里
变量检查
变量检查分为两部分
一部分是底部调试区左侧的GUI调试区
一部分是使用指令的调试区
我们先来看左侧的
在程序暂停后,左侧的GUI调试区会显示当前作用域中的所有变量

在这个部分右键变量也可以对变量进行一些操作
例如查看变量的基本信息,在终端打印对象等等

指令查看
很多博客都会在开始就讲LLDB的指令分为什么什么,是什么结构
我觉得不如从最简单的开始讲
查看变量最简单,最常用的指令就是PO
po指令的全称为print object
它会调用这个对象的 description 方法,给你一个“友好”的描述

与之类似但是不友好的是p指令
它用来打印“原始”数据,或者说C语言类型的数据,例如结构体
举一个具体的例子,view.frame就是一个结构体
如果你使用po去查看,只会出现这样

这个时候就要使用p指令

这样就可以显示数据的内容
除了查看,我们还可以修改变量
使用e可以来修改
它会在当前断点,动态执行你输入的任何代码

当然代码为oc语言风格,但是不需要使用分号
这篇文章不是很想在这里讲太多,所以实际上只讲了可能会用到的,以及一些GUI部分内容
关于如何详细用LLDB来调试,分析,以及关于指令行的详细运用会在之后出一篇进阶的博客来讲
参考文献:
- 运行,暂停,检查:探索如何使用LLDB进行有效调试
- LLDB 十分钟快速教程
