美文网首页
调试利器 — LLDB之断点编辑

调试利器 — LLDB之断点编辑

作者: 程醉不知归路 | 来源:发表于2019-04-04 01:14 被阅读0次

    转载请注明出处,谢谢

    调试是每个开发无法绕过的事情,甚至有时候调试所花的时间比编写代码花的更多。如果你想提高调试效率,了解一些高级的小技巧,可以继续阅读。

    简单试想一个场景。当你调试代码,复盘逻辑的时候,突然想输出几个log,怎么办?更多的时候,我们希望改变某个变量的值,或者让代码运行某个分支,以验证我们的猜想,做本地的全路径测试。怎么办?
    打一堆代码,然后重新运行?不仅麻烦,有时候还不能重新运行,会破坏上下文。提交代码的时候还得小心翼翼,别把调试的代码上传。
    这个时候你可以考虑下LLDB和强大的编辑断点。

    所谓工欲善其事必先利其器.
    今天就简单介绍下iOS开发的利器—LLDB
    我们平时的工作中,自测,调试占据了大量的时间.用好LLDB,可以大大提升我们的开发效率.

    什么是LLDB

    作为一名iOS开发, 对LLDB应该不会陌生.

    LLDB is a next generation, high-performance debugger.
    LLDB is the default debugger in Xcode on Mac OS X and supports debugging C, Objective-C and C++ on the desktop and iOS devices and simulator.
    作为xcode的默认debugger, 你没有理由不了解它

    其实我们平时一直都有和LLDB在打交道,只是没有意识到罢了.
    每次断点的时候,控制台左上角都有一行小字,(lldb),告诉我们lldb的低调的存在。我们经常用到的p(用于输出基本类型)或者po(用于输出 Objective-C 对象)也都是llldb的命令。
    Xcode本身更是将很多调试指令用UI形式展示了出来,比如断点调试的相关命令。
    我们的开发利器,Chisel,本质上也是一个LLDB插件的合辑。

    LLDB的可讲的东西太大太多, 限于篇幅问题, 我们这边就从编辑断点入手,简单介绍下LLDB在开发过程中的一些妙用

    LLDB妙用之编辑断点

    在xcode中双击一个断点, 你会看到下面这个图(这个就是Xcode的可视化LLDB调试指令)

    编辑断点

    Condition,这里可以输入条件表达式,满足条件的时候断点就会生效。
    Ingore,设置忽略断点次数。
    Options,选中之后, 会自动执行断点, 而不会中断程序, 非常好用。
    Action,重头戏。有6种类型。

    • AppleScript
    • Capture GPU Frame
    • Debugger Command
    • Log Message
    • Shell Command
    • Sound

    我们重点讲下Log Message和Debugger Command .其他几个感兴趣的可以自己去探索下. 比如下面这段 AppleScript(苹果自家的脚本,你可以做很多事情,你懂的)

    
    set dialogString to "Input a number here"
    set returnedString to display dialog dialogString default answer ""
    set returnedNumber to the text returned of returnedString
    
    try
        say returnedNumber
    end try
    
    

    Log Message

    这边有两个选项
    1. log message to console
    顾名思义,输出log信息到控制台。

    前面提到的痛点,一些临时性的,或者本地性的log, 写了之后还得删除,一不小心还容易上传到服务器.
    或者程序跑起来后,要加log,又不想打完代码重新重新编译.
    log message to console, 你值得拥有

    举个简单的例子

        for (int i = 0; i < 10; ++i) {
            NSLog(@"value:%d", i);
        }
    

    比如这样一条临时性的log,我根本就不需要在代码中写出来。
    可以用这样的等价命令实现同样的效果


    断点日志

    语法在图上已经说明了,
    %H,会输出断点被命中的次数;
    %B,会输出断点类的名字;
    两个@@中间可以写表达式,会输出表达式的值

    这是控制台输出结果


    日志结果

    当然你也可以普通断点, 然后po变量值. 不过有些批量的东西还是不希望每次都写的.而且有些场景也不太适合用断点.

    2. Speake message

    让你的断点会说话。甚至会唱歌. 这个其实和AppleScript的say命令是一样的.
    选择 Log Message, 勾选Speake message, 然后复制下面这段文字到message框中. 会有神奇的效果.

    碍,碍,碍,碍,泥刊着歌挽,塌,由打,由院。泥刊着歌棉、塌,由场,由款。腻们、来着里、池饭。爵的,饭,恨浩痴。哎,卧砍姓。腻们、来着里,池饭。救、像、卧给腻闷腊、棉、姨羊恨开信,哎!
    

    Debug common

    非常强大的一个功能!
    其实本质就是LLDB的命令。只是免去了每次在控制台输入这些命令的麻烦。同时可以方便快捷的添加condition,ignore和option。如果用命令行打就比较繁琐了。

    我们这边主要介绍几个非常实用的命令。

    Expression(表达式)

    这个命令很强大,其实很多命令都是它的别名而已。
    它可以动态改变某个变量的值。
    比如这段代码

        NSInteger status = 1;
        if (status == 0) {
            NSLog(@"do action 1");
        } else {
            NSLog(@"do action 2");
        }
    
    

    正常代码会走到 action 2 的逻辑分支。
    如果这个时候你想验证下 action 1的逻辑分支,怎么办?
    把status的值改成0,之后再重启Xcode.?NO!
    你只需要在判断语句之前,添加个断点, 编辑断点,
    输入如下Debug common, "e status = 0 "
    这样断点之后的status的值就变成0了。
    e 是 expression的简写

    讲几个实用的场景:

    1. 灰度开关
    我们APP中经常会有各种灰度开关. 对应不同的表现.用这个命令就可以很方便的在运行时改变开关的值.看不同状态下的UI和表现。开发过程中就可以非常方便的自测所有的场景。

    2. 网络请求
    比如网络回包,我们常见的写法.

             if (error) {
                 //error logic
                 return;
             }
    
             //succeed logic here
    

    这边我们只要在if这边加个断点, 输入命令, “e error == nil”
    就可以在后台接口不可用的时候, 跳过某些请求.
    或者在网络请求成功后, 让error不为nil , 就可以顺便检查下错误分支的逻辑.
    方便及时.

    当然仅仅控制代码的执行分支是不够的,我们还需要数据.这个时候你可能需要用到变量.

    变量

    前面说到,我们可以用expression改变变量的值。其实我们还可以创造变量。
    变量必须以美元符号开头,比如

    e int  $a = 5
    e exitValue = $a + 5
    

    我们创造了一个变量 $a,并且可以在后续拿来使用。
    这个也是一个非常强大且充满想象力的功能, 在mock数据和控制分支的时候.经常会有意想不到的奇效.

    比如这段命令

    e id $nvc = [[[UIApplication sharedApplication] keyWindow] rootViewController]
    e id $vc = [[UIViewController alloc] init]
    e (void)[[$vc view] setBackgroundColor:[UIColor yellowColor]]
    e (void)[$vc setTitle:@"Test"]
    e (void)[$nvc pushViewController:$vc animated:YES]
    

    就几乎可以在任何地方凭空弹出一个VC.
    你还可以做些更酷的事情.比如在某些条件下弹出这个VC,读取本地文件中的数据进行展示之类的.

    最后讲一个功能, 函数调用

    call

    还是举上面的例子, 比如你断点进入了error分支, 这个时候你又想走succeed分支的代码. 有些情况下又不能重新走一遍流程.也就是只有一次机会。
    这个时候你可以在error分支调用 “成功”分支的逻辑

    call [self requestSucceed:dic]
    

    搞定!如果不够,再组合几条命名.

    其实 p&po &e &call 命令都是 expression 的别名
    所以 上面那条也可以写成

    e [self requestSucceed:dic]
    

    其他一些场景

    比如改变控件的背景色, 看看它到底在哪里
    改变控件的位置, 可见性, 交互性等.
    很多好用的工具本质上都是LLDB命令的封装.

    前面提到的场景都是一些简单的例子.只是为了简单说明这些命名的作用.
    熟练使用这些命令之后, 你会发现更多的实用场景.而这些会让你的调试自测之路变得更加轻松,节省很多时间.

    然后除了前面提到的一些命令外, 还有很多实用的命名, 比如thread backtrace, thread return等.
    学习笔记之—认识Xcode中的重要成员:lldb调试器 - 滴水微澜 - 博客园

    总结

    讲了这么多. 总结下今天的内容

    • LLDB是xcode的默认debugger, 你值得拥有.
    • Xcode本身有很多LLDB的可视化操作. 断点编辑是一个非常强大使用的功能.熟练使用后可以大大提高效率.常用的命令也就几个.关键在发挥想象力.
    • 本文只是通过断点编辑揭露LLDB功能的冰山一角.LLDB能做的事情远超你的想象。比如LLDB+Python。比如脚本桥接script bridging value,检查SBValue等
    • 最后,要优雅

    参考资料

    LLDB官网
    Dancing in the Debugger — A Waltz with LLDB

    相关文章

      网友评论

          本文标题:调试利器 — LLDB之断点编辑

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