Xcode 调试之 LLDB

LLDB 是 Xcode 中的默认调试器,支持调试 C、Objective-C、C++,用 LLDB 调试代码的好处不必多说,基本 Xcode 中常见的调试方式 LLDB 都支持,但 LLDB 还可以在运行时写和运行一些简单代码、运行 Python 代码来扩展调试的方式。

LLDB

现在让我们来总结写 LLDB 都有哪些调试方式吧~

打印

我们最常用的可能就是进行打印操作,在打下断点,程序暂时停止,在 console 中写命令打印一些变量的值:

  • po oc对象
    会调用oc对象的description方法,将这个对象打印出来
  • p 基本数据类型
    可以使用 print、或其简写 p 打印一些基本数据类型

Help

  • help 命令
    下面讲的所有命令都可以通过 help 查看其具体含义、信息

Breakpoint

可以直接用写命令的方式打断点、调试、编辑断点信息:

  • b 某文件.m:30
    给 某文件的第30行打下一个断点

  • br l
    列出当前工程的所有断点信息

  • br delete n
    删除第n个断点

  • br enable n
    使第n个断点有效

  • br disable n
    使第n个断点失效

  • br set -n 某方法
    设置关于这个方法的符号断点,在调用这个方式时,程序都会暂停

  • br mod -c "某条件" n
    设置条件断点,给第n个断点加一个条件

在断点停下后,还可以像按这些键一样,调试断点:


调试断点
  • c
    Continue,继续执行
  • n
    StepOver,一步一步执行方法
  • s
    StepInto,进入方法调用里面
  • finish
    StepOut,跳出方法调用

Expression

expr + OC 代码,在运行时可以执行,对于输出一些运行时才会确定的变量十分有用。

  • expr (void) NSLog(@"balhbalh")
    简单的打印操作
  • expr + 结构体
    expr 可以打印结构体的值


    打印self.view.bounds
  • expr + 变量赋值
    这个会实际改变变量的值


    运行时改变了 num 的值
  • expr + 方法调用
    最神奇的莫过于这个,在运行时直接调用指定方法,给运行时加一些“行为”,比如
在ViewController出现时,给这个断点添加一个行为

给断点添加了一个行为,执行 expr 后面的方法,然后 continue。
这样每次在ViewController出现时,会执行这个 segue ,推出后面的 Controller,如图:

每次蓝色的VC出现时,会执行segue,弹出黄色的VC

Backtrace

  • bt
    当程序 crash 掉时,可以用 bt 查看程序运行时函数调用的堆栈信息
  • bt all
    bt 显示的是当前线程函数调用的信息,可以加 all 显示所有线程的堆栈信息

Thread

可以操作线程,显示当前线程信息,在运行时,直接改变方法调用的返回值

  • thread list
    显示所有线程信息
  • thread select n
    选择第n个线程
  • thread backtrace
    显示当前 thread 的堆栈信息
  • thread backtrace all
    显示所有 thread 的堆栈信息
  • thread until i
    使线程运行,并在第 i 行时停下
  • thread return 返回值
    直接改变当前方法调用的返回值


    isYesOrNo 本来为YES,但是通过 thread return 直接让其值返回NO

Frame

运行时直接查看变量的值

  • frame variable
    如上图,frame variable 直接查看当前变量的值
  • frame variable 变量名
    查看指定变量名的值

Watchpoint

当变量变化时,程序暂停,显示 watchpoint 的变化

  • watchpoint list
    显示当前所有 watchpoint
  • watchpoint set variable 变量名
    给变量设置 watchpoint
  • watchpoint modify -c "条件" n
    给第n个断点添加条件,只有满足条件时,watchpoint 才会触发
  • watchpoint modify -c "" n
    条件置空时,即为给这个 watchpoint 删除条件
  • watchpoint set expression -- 内存地址
    对任意内存地址进行观察

Script

lldb 内置了 Python 的脚本解释器,可以解释运行 Python 代码

  • breakpoint command add -s python n
    给第n个断点添加python代码
给断点1添加简单的python代码,每次停下来时,会执行这段代码
  • breakpoint command add -F "python文件名"."python方法名" n
    给第n个断点添加导入的 python 文件中的方法调用

Command

  • command script import "文件路径/文件名"
    导入已有的脚本文件,在调试时可以直接用这个文件
  • command import "文件路径/文件名"
    导入已有的 lldb 调试脚本文件
  • command unalias pf
    删除用户自定义的 aliases
  • command history
    打印在当前运行状态下,lldb 调试时command 历史

示例:

  1. 新建一个 empty 文件,文件后缀名为 py,内容为:
def print_locals(frame, bp_loc, internal_dict):
    variables = frame.GetVariables(False,True,False,True)
    for i in range(0, variables.GetSize()):
        variable = variables.GetValueAtIndex(i)
        print variable

大概意思为,定义一个方法,会将当前的变量一个一个打印下来
frame 指当前堆栈信息,bp_loc 指断点的具体位置,internal_dict 这个python 文件的一些参数信息

2.导入 python 代码
3.给断点加入 python 代码中定义的方法
如图所示:


调试断点时,使用一段已有的 python 代码

Alias

当遇到较为复杂的命令,可以给这些命令定义一个别名,每次调用别名即可。

  • command alias "别名" 具体命令
    给具体命令设置一个别名
给 expr 命令加了一个别名 pf

上面的方法存在一个问题,设置的别名只在当前运行过程有效,下次就失效了,怎么持久化呢?
可以将这些命令封装起来,保存在电脑中,每次调试时都可使用。

  • 1.新建 lldbinit 文件,在终端中输入
    $ touch ~/.lldbinit
    $ open ~/.lldbinit


    输入命令,图中定义了一个pf命令

2.重启Xcode,再次编译运行
3.打断点,并输入 pf

这一次只要 .lldbint 文件存在,pf别名就一直可以使用

Chisel 是 Facebook 开源的一款 lldb 命令集合文件,GitHub 地址。我们可以直接使用一些定义好的 lldb 命令来调试程序。
安装十分简单,确保 Mac 已经安装了 homebrew 环境
$ brew update
$ brew install chisel
安装成功后会出现

安装成功

并且提示要将框中出现的命令加在刚刚生成的那个 .lldbint 文件中。
重启 Xcode 之后,每次就可以使用这些命令了。
在 lldb 中输入 help,我们发现最下面出现了一些用户自定义命令,这就是 Chisel 中的。
比较常用的有border,给视图加边框;hide,隐藏视图;mask,给视图加遮罩;presponder,显示响应者链……

关于 Xcode 调试的文章先总结到这里,希望以后能继续补充完善🤖

参考文章
Xcode LLDB Tutorial
The LLDB Debugger
Dancing in the Debugger — A Waltz with LLDB

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

推荐阅读更多精彩内容

  • LLDB的Xcode默认的调试器,它与LLVM编译器一起,带给我们更丰富的流程控制和数据检测的调试功能。平时用Xc...
    CoderSC阅读 1,344评论 0 2
  • 一直以来在console中使用最基本的print与po命令来调试程序,通过这两个命令可以应付大多数的情况下的调试需...
    木夜溯阅读 1,013评论 1 1
  • [转]浅谈LLDB调试器文章来源于:http://www.cocoachina.com/ios/20150126/...
    loveobjc阅读 2,477评论 2 6
  • 转载 与调试器共舞 - LLDB 的华尔兹: https://objccn.io/issue-19-2/ 推荐:i...
    F麦子阅读 3,325评论 0 10
  • 这两天可能是我这辈子过得最煎熬的两天了, 我渐渐很清楚看清楚, 人生在地球,肯定背负“命”和“义”这两个东西, 人...
    j_haven阅读 369评论 0 0