设为首页 加入收藏

TOP

使用LLDB调试Swift(一)
2017-10-18 09:07:41 】 浏览:6958
Tags:使用 LLDB 调试 Swift

作为开发者,我们工作70%的时间都用于调试。20%用于架构设计和团队沟通,仅有10%的时间用于写代码。


因此如何让这70%的时间变得高效显得尤为重要。LLDB是个很好的选择。尽管Xcode拥有功能完善的调试面板,控制台仍然是调试中重要的组成部分。接下来我会探讨一些工作中常用到的一些LLDB调试技巧。


从哪开始?


LLDB拥有大量有用的调试工具。我会选一些重要的命令讨论:


下面列出了LLDB常用命令的描述和例子。你可以保存该图片方便以后查阅。



1.获取变量值和状态


命令:expressioneprintpop


调试工具最基本的功能是打印和修改变量的值。expressione就是这样的工具。你可以在运行时执行几乎任何表达式或命令。


假设你正在调试valueOfLifeWithoutSumOf()方法,该方法用于两数相加并与42相减。


现在运行得到了错误的结果。你可以像下图这样修改代码尝试定位问题:


更好的方式是使用expression命令在运行时修改变量的值。设置断点并运行。


按照LLDB格式打印变量的值:


完全相似的方式执行表达式:


expression命令有一些选项。LLDB使用双破折号--分隔选项和表达式:


expression拥有大约30个选项。这些选择都值得你来探索。终端输入以下命令可以获取详细的文档:


下面列出了几个比较常用的选项:


假如现在有个logger对象。该对象拥有一些字符串和结构体作为属性。如果只想打印层级1的属性,可使用-D选项:


LLDB默认会递归打印对象的所有属性,展示非常详尽的内容:


也可以像如下使用 e -O --或者别名 po来打印:


这样直接打印可读性不高。通过实现 CustomStringConvertible协议中的var description: String { return ...}属性,po会返回可读性更好的描述。


在这段开头也提到了print命令。除了print命令没有可用选项无需传递参数外,print <expression/variable>expression --<expression/variable>几乎一样。


2.获取执行环境+特定语言命令


bugreportframelanguage


你是否经常需要拷贝粘贴日志到任务管理器中来定位问题。LLDB的bugreport命令可以生成一份详细的app当前状态的报告。该命令对于想要延迟追踪定位问题非常有用。为了保存app的状态,你可以使用bugreport来生成报告。


生成的报告如下:


!Example of bugreport command output


frame命令可以打印出当前线程的栈帧:


使用如下命令来快速了解你在哪和当前执行环境:


该信息对文章后面提到的断点管理非常有用。


LLDB有一些针对特定语言的命令。这些命令有针对C++,Objective-C,Swift和RenderScript的。这篇文章中只讨论针对swift的两个命令:demanglerefcount


demangle命令正如其名字描述的一样用于修复损坏的Swift类型名(编译期间为避免命名空间问题而产生)。想要了解更多可以观看WWDC14 session - "Advanced Swift Debugging in LLDB"


refcount命令的命名也非常直观,可用于显示对象的引用计数。让我们回到前面讨论过的用于输出的对象 - logger


这对于调试查找内存泄露问题是很有帮助的。


3.执行流程控制


processbreakpointthread


这是我最喜欢的部分。使用LLDB的这些命令(尤其是breakpoint)可以让调试变得更自动化。有助于提升调试速度。


process用于控制要调试的进程,可把LLDB依附到特定target或从target上解绑。运行target时Xcode已经为我们做好了将LLDB依附到该进程的工作,所以这里不再讨论LLDB的依附。可通过阅读苹果手册-"Using LLDB as a Standalone Debugger"来了解如何依附LLDB到进程中。


process status用于打印当前进程及断点处的相关信息:


使用如下命令可继续执行:


这等同于Xcode调试面板中 "continue" 按钮:


breakpoint用于断点的各种操作。这里不会讨论这些太常见的命令:breakpoint enablebreakpoint disable,和breakpoint delete


使用list子命令可以打印出所有断点:


列表中的第一个数字是断点ID,可用于引用对应的断点。下面从控制台设置一个新的断点:


上面例子中-f选项用于指明断点所在的文件。-l选项用于指明断点所在的行数。对于上面例子有个更简洁的表达:


也可以使用以命令对某个方法设置断点:


有时候需要断点仅命中一次。命中后随即删除该断点。通过如下命令行可以实现:


下面进入最有趣的部分-断点自动化。你知道可以设置特定动作用于断点发生时执行吗?调试时你是否喜欢在代码中使用print()来打印你感兴趣的值?下面有个更好的方法。


通过breakpoint command可以设置命中断点后执行的命令。甚至可以设置不会打断执行的"透明"断点。从技术上来说"透明"断点已然会打断执行,但通过在命令链中添加continue命令可以变得无感知。


通过breakpoint command list <breakpoint id>命令可以检查一遍命令是否都正确:


当断点命中时控制台会有如下输出:


这正是我们所期望的。甚至可以在命令链的后面添加continue来防止执行被打断。


输出结果:


通过thread和其子命令可以完全的控制执行流程:step-overstep-instep-outcontinue。这些命令等同于Xcode调试面板里用于控制执行流程的按钮。


对于这些命令也有预定义的快捷命令:


通过info子命令可获取关于当前线程的更多信息:


list子命令用于显示当前所有活跃线程:


其他


commandplatformgui


LLDB中有一个用于管理其他命令的命令。听起来很奇怪,但非常有用。首先,该命令允许你从文件执行LLDB命令。因此你可以创建一个包含大量有用命令的脚本当做一个命令来执行。下面是一个包含两条命令的文件:


真正命令执行如下:


不幸的是,无法在执行脚本文件时传递参数(除非在脚本文件中创建一个可用变量)。


script子命令提供了一些高级用法,可用于管理(adddeleteimportlist)自定义的Python脚本。script是的命令自动化变成了可能。更详尽的信息请查阅Python scripting for LLDB指南。示例中,我们创建了一个功能非常简单的script.py脚本,该脚本仅包含了print_hello()命令用于打印"Hello Debug个!"到控制台:


接下来需要导入该Python脚本,导入后可直接使用脚本命令:


status子命令可用于快速查看当前平台信息。status会打印出:SDK路径,处理器架构,操作系统版本和该SDK支持的可用设备列表。


Xcode中无法使用LLDB的可视化模式,但可以在终端中使用。


!This

首页 上一页 1 2 下一页 尾页 1/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇为什么说Flutter是革命性的? 下一篇用 C 语言对 Gtk+ 应用进行功能测..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目