Xcode 调试之 LLDB

作者: 花与少年_ | 来源:发表于2017-05-17 17:51 被阅读190次

    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

    相关文章

      网友评论

        本文标题:Xcode 调试之 LLDB

        本文链接:https://www.haomeiwen.com/subject/qbarxxtx.html