博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
XCode调试器LLDB
阅读量:5246 次
发布时间:2019-06-14

本文共 3255 字,大约阅读时间需要 10 分钟。

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

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

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

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

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

LLDB

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

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

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

基础

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

    720299-20180222171112991-1849848516.png

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

help

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

print

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

    720299-20180222171143345-22637080.png

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

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

expression

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

    720299-20180222171226792-1692790731.png

  • 这不仅会改变调试器中的值,实际上它改变了程序中的值。这时候继续执行程序,将会打印 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 * 1938(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 typeerror: 1 errors parsing expression// 悲剧了,LLDB 无法确定涉及的类型 (译者注:返回的类型)。这种事情常常发生,给个说明就好了:(lldb) p (char)[[$array objectAtIndex:$a] characterAtIndex:0]'M'(lldb) p/d (char)[[$array objectAtIndex:$a] characterAtIndex:0]77

转载于:https://www.cnblogs.com/ShaoYinling/p/8459513.html

你可能感兴趣的文章
Zerver是一个C#开发的Nginx+PHP+Mysql+memcached+redis绿色集成开发环境
查看>>
多线程实现资源共享的问题学习与总结
查看>>
Learning-Python【26】:反射及内置方法
查看>>
torch教程[1]用numpy实现三层全连接神经网络
查看>>
java实现哈弗曼树
查看>>
转:Web 测试的创作与调试技术
查看>>
python学习笔记3-列表
查看>>
程序的静态链接,动态链接和装载 (补充)
查看>>
关于本博客说明
查看>>
线程androidAndroid ConditionVariable的用法
查看>>
stap-prep 需要安装那些内核符号
查看>>
2016寒假自学笔记
查看>>
转载:ASP.NET Core 在 JSON 文件中配置依赖注入
查看>>
socket初识
查看>>
磁盘测试工具
查看>>
代码变量、函数命名神奇网站
查看>>
redis cli命令
查看>>
Problem B: 占点游戏
查看>>
python常用模块之sys, os, random
查看>>
HDU 2548 A strange lift
查看>>