简体   繁体   English

Xcode LLDB 中的 13 个奇怪行为

[英]Xcode 13 strange behavior in LLDB

When using expressions(ex. po) in console the debugger strongly retains and does not release objects.在控制台中使用表达式(例如 po)时,调试器会强烈保留并且不会释放对象。 The result is that the objects, that would otherwise deinitialize, leak.结果是对象,否则将取消初始化,泄漏。

Steps to reproduce the issue:重现问题的步骤:

  1. Open a new Xcode iOS app project.打开一个新的 Xcode iOS 应用程序项目。
  2. Create a new class and put a log in deinit.新建一个class,在deinit里面放一个log。
class Something {
    deinit {
        print("Something deinited")
    }
}
  1. Open ViewController.swift, override viewDidLoad and make an instance of the class.打开 ViewController.swift,覆盖 viewDidLoad 并创建 class 的实例。
override func viewDidLoad() {
    super.viewDidLoad()

    let object = Something()
    print(object)
}
  1. Set a breakpoint just after the object initialization line.在 object 初始化行之后设置一个断点。
  2. Run the app on simulator or device.在模拟器或设备上运行应用程序。
  3. First time when the execution stops at the breakpoint just click continue and see the deinitialization log from the object instance printed.第一次在断点处停止执行时,只需单击继续并查看打印的 object 实例的取消初始化日志。
  4. Verify that the object instance has been successfully deinitialized from the memory using memory graph.使用 memory 图验证 object 实例已从 memory 成功取消初始化。
  5. Run the app again but this time execute "po object" expression in console.再次运行应用程序,但这次在控制台中执行“po object”表达式。
  6. Continue继续
  7. See the absence of deinit log in console.查看控制台中没有 deinit 日志。
  8. Open memory graph in Xcode and see the Something object leaked.打开 Xcode 中的 memory 图,可以看到泄漏的 Something object。

I wonder if this is a lldb bug or anyone has an idea of what else could this be.我想知道这是否是一个 lldb 错误,或者有人知道这可能是什么。

This is not the best behavior, but it's hard to fix.这不是最好的行为,但很难修复。 po - ie expr -O -- runs in two parts. po - 即expr -O --分两部分运行。 It first takes the expression you provide, and runs it through the clang or swift compiler to produce some code that can run in the debugee such that it behaves "as if the expression had been typed in your sources at the point where you are stopped."它首先获取您提供的表达式,并通过 clang 或 swift 编译器运行它,以生成一些可以在调试对象中运行的代码,这样它的行为“就像在您停止时在源代码中键入表达式一样。 “ The result of the last statement in the expression is captured as the value of the expression.表达式中最后一条语句的结果被捕获为表达式的值。

That's the p part.那是p部分。 For po , lldb takes the result of that expression and runs another expression to fetch the "object description" of that resultant object.对于po ,lldb 获取该表达式的结果并运行另一个表达式来获取该结果 object 的“对象描述”。

The first part, which captures something as an escaping result, is what causes the extra retain.第一部分将某些内容捕获为 escaping 结果,这是导致额外保留的原因。 Note however, that the "expression" can be anything.但是请注意,“表达式”可以是任何东西。 For instance, you might call a function that generates an object, in which case the result needs to be retained... We'd have to monkey with the compiler to get it to retain in some cases and not in others, and that goes against the goal of being a faithful representation of the compiler.例如,您可能会调用生成 object 的 function,在这种情况下,结果需要保留……我们必须与编译器一起修改,以使其在某些情况下保留,而在其他情况下不保留,这样就可以了违背了成为编译器忠实代表的目标。 And lldb doesn't really know what was in the expression, it just submits it to the compiler as text and the compiler figures it out.并且 lldb 并不真正知道表达式中的内容,它只是将其作为文本提交给编译器,然后由编译器计算出来。

TL;DR it's a known issue with no easy solution in the context of the expression parser. TL;DR 这是一个已知问题,在表达式解析器的上下文中没有简单的解决方案。

The "workaround" is not to use a fully general expression evaluator to print local variables, which does seem a bit overkill. “解决方法”是不使用完全通用的表达式求值器来打印局部变量,这看起来有点矫枉过正。 Fortunately, lldb has a command: frame var (short name v ) that presents the values of variables by reading memory and interpreting it using debug info and the type system directly.幸运的是,lldb 有一个命令: frame var (简称v ),它通过读取 memory 并直接使用调试信息和类型系统对其进行解释来显示变量的值。 lldb can do that w/o changing any state in your program. lldb 可以在不更改程序中的任何 state 的情况下做到这一点。 v is also a lot faster, and more reliable than ginning up a contextually aware expression, compiling and running it. v也比生成上下文感知表达式、编译和运行它更快、更可靠。 There's a object description variant vo if you need the description string rather than the ivars of the object.如果您需要描述字符串而不是 object 的 ivar,则有一个 object 描述变体vo

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM