zoukankan      html  css  js  c++  java
  • XCode调试器LLDB

    与调试器共舞 - LLDB 的华尔兹

    • 你是否曾经苦恼于理解你的代码,而去尝试打印一个变量的值?
    NSLog(@"%@", whatIsInsideThisThing);
    
    • 或者跳过一个函数调用来简化程序的行为?
    NSNumber *n = @7; // 实际应该调用这个函数:Foo();
    
    • 或者短路一个逻辑检查?
    if (1 || theBooleanAtStake) { ... }
    
    • 或者伪造一个函数实现?
    int calculateTheTrickyValue {
      return 9;
    
      /*
       先这么着
       ...
       */
    }
    
    • 并且每次必须重新编译,从头开始?

    • 构建软件是复杂的,并且 Bug 总会出现。一个常见的修复周期就是修改代码,编译,重新运行,并且祈祷出现最好的结果。

    • 但是不一定要这么做。你可以使用调试器。而且即使你已经知道如何使用调试器检查变量,它可以做的还有很多。

    • 这篇文章将试图挑战你对调试的认知,并详细地解释一些你可能还不了解的基本原理,然后展示一系列有趣的例子。现在就让我们开始与调试器共舞一曲华尔兹,看看最后能达到怎样的高度。

    LLDB

    • LLDB 是一个有着 REPL 的特性和 C++ ,Python 插件的开源调试器。LLDB 绑定在 Xcode 内部,存在于主窗口底部的控制台中。调试器允许你在程序运行的特定时暂停它,你可以查看变量的值,执行自定的指令,并且按照你所认为合适的步骤来操作程序的进展。(这里有一个关于调试器如何工作的总体的解释。)

    • 你以前有可能已经使用过调试器,即使只是在 Xcode 的界面上加一些断点。但是通过一些小的技巧,你就可以做一些非常酷的事情。GDB to LLDB 参考是一个非常好的调试器可用命令的总览。你也可以安装 Chisel,它是一个开源的 LLDB 插件合辑,这会使调试变得更加有趣。

    • 与此同时,让我们以在调试器中打印变量来开始我们的旅程吧

    基础

    • 这里有一个简单的小程序,它会打印一个字符串。注意断点已经被加在第 8 行。断点可以通过点击 Xcode 的源码窗口的侧边槽进行创建。

      • 程序会在这一行停止运行,并且控制台会被打开,允许我们和调试器交互。那我们应该打些什么呢?

    help

    • 最简单命令是 help,它会列举出所有的命令。如果你忘记了一个命令是做什么的,或者想知道更多的话,你可以通过 help command 来了解更多细节,例如 help print 或者 help thread。如果你甚至忘记了 help 命令是做什么的,你可以试试 help help。不过你如果知道这么做,那就说明你大概还没有忘光这个命令。

    print

    • 打印值很简单;只要试试 print 命令:

    • LLDB 实际上会作前缀匹配。所以你也可以使用 prin,pri,或者 p。但你不能使用 pr,因为 LLDB 不能消除和 process 的歧义 (幸运的是 p 并没有歧义)。

    • 你可能还注意到了,结果中有个 $0。实际上你可以使用它来指向这个结果。试试 print $0 + 7,你会看到 106。任何以美元符开头的东西都是存在于 LLDB 的命名空间的,它们是为了帮助你进行调试而存在的。

    expression

    • 如果想改变一个值怎么办?你或许会猜 modify。其实这时候我们要用到的是 expression 这个方便的命令。

    • 这不仅会改变调试器中的值,实际上它改变了程序中的值。这时候继续执行程序,将会打印 42 red balloons。神奇吧。

    • 注意,从现在开始,我们将会偷懒分别以 p 和 e 来代替 print 和 expression。

    什么是 print 命令

    • 考虑一个有意思的表达式:p count = 18。如果我们运行这条命令,然后打印 count 的内容。我们将看到它的结果与 expression count = 18 一样。和 expression 不同的是,print 命令不需要参数。比如 e -h +17 中,你很难区分到底是以 -h 为标识,仅仅执行 +17 呢,还是要计算 17 和 h 的差值。连字符号确实很让人困惑,你或许得不到自己想要的结果。

    • 幸运的是,解决方案很简单。用 -- 来表征标识的结束,以及输入的开始。如果想要 -h 作为标识,就用 e -h -- +17,如果想计算它们的差值,就使用 e -- -h +17。因为一般来说不使用标识的情况比较多,所以 e -- 就有了一个简写的方式,那就是 print。

    • 输入 help print,然后向下滚动,你会发现:

    'print' is an abbreviation for 'expression --'.
    (print是 `expression --` 的缩写)
    

    打印对象

    • 尝试输入
    p objects
    
    • 输出会有点啰嗦
    (NSString *) $7 = 0x0000000104da4040 @"red balloons"
    
    • 如果我们尝试打印结构更复杂的对象,结果甚至会更糟
    (lldb) p @[ @"foo", @"bar" ]
    
    (NSArray *) $8 = 0x00007fdb9b71b3e0 @"2 objects" 
    
    • 实际上,我们想看的是对象的 description 方法的结果。我么需要使用 -O (字母 O,而不是数字 0) 标志告诉 expression 命令以 对象 (Object) 的方式来打印结果。
    (lldb) e -O -- $8
    <__NSArrayI 0x7fdb9b71b3e0>(
    	foo,
    	bar
    )
    
    • 幸运的是,e -o -- 有也有个别名,那就是 po (print object 的缩写),我们可以使用它来进行简化:
    (lldb) po $8
    <__NSArrayI 0x7fdb9b71b3e0>(
    	foo,
    	bar
    )
    (lldb) po @"lunar"
    lunar
    (lldb) p @"lunar"
    (NSString *) $13 = 0x00007fdb9d0003b0 @"lunar"
    

    变量

    • 现在你已经可以打印对象和简单类型,并且知道如何使用 expression 命令在调试器中修改它们了。现在让我们使用一些变量来减少输入量。就像你可以在 C 语言中用 int a = 0 来声明一个变量一样,你也可以在 LLDB 中做同样的事情。不过为了能使用声明的变量,变量必须以美元符开头。
    (lldb) e int $a = 2
    (lldb) p $a * 19
    38
    (lldb) e NSArray *$array = @[ @"Saturday", @"Sunday", @"Monday" ]
    (lldb) p [$array count]
    2
    (lldb) po [[$array objectAtIndex:0] uppercaseString]
    SATURDAY
    (lldb) p [[$array objectAtIndex:$a] characterAtIndex:0]
    error: no known method '-characterAtIndex:'; cast the message send to the method's return type
    error: 1 errors parsing expression
    // 悲剧了,LLDB 无法确定涉及的类型 (译者注:返回的类型)。这种事情常常发生,给个说明就好了:
    
    (lldb) p (char)[[$array objectAtIndex:$a] characterAtIndex:0]
    'M'
    (lldb) p/d (char)[[$array objectAtIndex:$a] characterAtIndex:0]
    77
    
  • 相关阅读:
    loadrunner—事务、TPS
    loadrunner—集合点rendezvous
    loadrunner—web_submit_data
    阿里云的docker仓库登陆打标签
    linux 下安装git服务器
    解决mvn clean后打包错:Cannot create resource output directory
    eclipse中创建的spring-boot项目在启动时指定加载那一个配置文件的设置
    docker命令
    springboot所有pom依赖
    pthon小游戏
  • 原文地址:https://www.cnblogs.com/ShaoYinling/p/8459513.html
Copyright © 2011-2022 走看看