Xcode 13 LLDB中的奇怪行为

发布于 2025-01-21 08:00:19 字数 774 浏览 4 评论 0原文

当在控制台中使用表达式(Ex。PO)时,调试器强烈保留并且不会释放对象。结果是,这些物体(否则会脱位)泄漏。

复制问题的步骤:

  1. 打开一个新的Xcode IOS应用程序项目。
  2. 创建一个新的类并在Deinit中登录。
class Something {
    deinit {
        print("Something deinited")
    }
}
  1. 打开ViewController.swift,覆盖ViewDidload,并制作一个类实例。
override func viewDidLoad() {
    super.viewDidLoad()

    let object = Something()
    print(object)
}
  1. 在对象初始化行之后设置断点。
  2. 在模拟器或设备上运行该应用程序。
  3. 第一次执行在断点处停止时,只需单击“继续”,然后查看“对象实例”打印的除静脉化日志。
  4. 使用内存图验证对象实例已从内存中成功地从内存中进行了定位。
  5. 再次运行该应用程序,但此时间在控制台中执行“ PO OBOCT”表达式。
  6. 继续
  7. 查看控制台中缺少DEINIT日志。
  8. 在XCode中打开内存图,然后查看某物对象泄漏。

我想知道这是否是LLDB错误,还是任何人都知道这可能是什么。

When using expressions(ex. po) in console the debugger strongly retains and does not release objects. The result is that the objects, that would otherwise deinitialize, leak.

Steps to reproduce the issue:

  1. Open a new Xcode iOS app project.
  2. Create a new class and put a log in deinit.
class Something {
    deinit {
        print("Something deinited")
    }
}
  1. Open ViewController.swift, override viewDidLoad and make an instance of the class.
override func viewDidLoad() {
    super.viewDidLoad()

    let object = Something()
    print(object)
}
  1. Set a breakpoint just after the object initialization line.
  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.
  4. Verify that the object instance has been successfully deinitialized from the memory using memory graph.
  5. Run the app again but this time execute "po object" expression in console.
  6. Continue
  7. See the absence of deinit log in console.
  8. Open memory graph in Xcode and see the Something object leaked.

I wonder if this is a lldb bug or anyone has an idea of what else could this be.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

心奴独伤 2025-01-28 08:00:19

这不是最好的行为,但很难解决。 PO - IE expr -o-以两部分运行。它首先采用您提供的表达式,并通过clang或Swift编译器运行它,以产生一些可以在Debugee中运行的代码,以使其行为“好像表达式在您停止的位置都在您的源中键入。 “表达式中最后一个语句的结果被捕获为表达式的值。

那就是p零件。对于po,LLDB获取该表达式的结果,并运行另一个表达式以获取该结果对象的“对象描述”。

第一部分将某些东西视为逃脱的结果,是导致额外保留的原因。但是请注意,“表达”可以是任何东西。例如,您可以调用生成对象的函数,在这种情况下,结果需要保留...我们必须与编译器猴子以在某些情况下而不是在其他情况下将其保留,而这种情况则是反对成为编译器的忠实代表的目标。而且LLDB并不真正知道表达式中的内容,它只是将其作为文本提交给编译器,并且编译器将其弄清楚。

Tl; dr这是一个已知的问题,在表达解析器的上下文中没有简单的解决方案。

“解决方法”不是使用完全一般的表达式评估器来打印本地变量,这似乎有点过大。幸运的是,LLDB具有一个命令:frame var(短名称v),它通过读取内存和使用调试信息和类型系统来读取变量值。 LLDB可以通过更改程序中的任何状态来做到这一点。 v也比插入上下文意识到的表达式,编译和运行它更快,更可靠。有一个对象描述变体vo如果您需要描述字符串而不是对象的ivars。

This is not the best behavior, but it's hard to fix. po - i.e. expr -O -- runs in two parts. 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." The result of the last statement in the expression is captured as the value of the expression.

That's the p part. For po, lldb takes the result of that expression and runs another expression to fetch the "object description" of that resultant object.

The first part, which captures something as an escaping result, is what causes the extra retain. 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. 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.

TL;DR it's a known issue with no easy solution in the context of the expression parser.

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 can do that w/o changing any state in your program. v is also a lot faster, and more reliable than ginning up a contextually aware expression, compiling and running it. There's a object description variant vo if you need the description string rather than the ivars of the object.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文