gpt4 book ai didi

swift - LLDB 无法检查变量(在 Xcode 中)

转载 作者:搜寻专家 更新时间:2023-10-30 22:23:58 37 4
gpt4 key购买 nike

特别是print命令通常(80-90% 的失败率)不起作用

我已经验证过:
https://developer.apple.com/library/content/qa/qa1947/_index.html

示例 1

(lldb) p prevMsg



错误:无法实现:无法获得 runOnce 的值:从值中提取数据失败错误:在 DoExecute 中出错,无法 PrepareToExecuteJITExpression

示例 2 一个更典型的示例,让您进入计算的石器时代:

(lldb) p activeNetworkRequests



错误:执行被中断,原因:EXC_BAD_ACCESS(代码=1,地址=0x1700530)。进程已经返回到表达式求值前的状态。

自 Xcode 7 以来,这似乎变得越来越糟。

从闭包的封闭函数范围内打印变量特别无望。

代码库不小,大约15K行。在这里隔离和重现所有代码是不切实际的。

肯定其他人也遇到过这种情况吗?

更新:我被告知表达式的优点 --unwind-on-error=0 -- 问题中的变量,大概是 example2

更新 2:

代码:
Util.log("Returning \(key) from file cache", [.Caches])

输出:
08:03:11.201 v2.0.64d other TwoStageCache.swift objectForKey(_:completion:)[95]: Returning https://example.server.com/Storage/Retrieve?FileName=accounts/person@domain.com/resource/47a58660-26d1-11e7-8e7f-c9f4cd679b03.html from file cache

(所以 key 的值是可以的)
(lldb) fr var key
(URL) key = unable to read data
(lldb) print key
error: Execution was interrupted, reason: EXC_BAD_ACCESS (code=1, address=0x1d787583).
The process has been returned to the state before expression evaluation.

如果我们看一下崩溃:
(lldb) expression --unwind-on-error=0 -- key

libobjc.A.dylib`objc_retain:
0x22562b0 <+0>: pushl %ebp
0x22562b1 <+1>: movl %esp, %ebp
0x22562b3 <+3>: subl $0x8, %esp
0x22562b6 <+6>: calll 0x22562bb ; <+11>
0x22562bb <+11>: popl %ecx
0x22562bc <+12>: movl 0x8(%ebp), %eax
0x22562bf <+15>: testl %eax, %eax
0x22562c1 <+17>: je 0x22562e1 ; <+49>
0x22562c3 <+19>: movl (%eax), %edx
-> 0x22562c5 <+21>: testb $0x2, 0x10(%edx)

从:
1 $__lldb_expr(UnsafeMutablePointer<Any>) -> ()
2 Beta Viewer`@objc AppDelegate.init() -> AppDelegate:
3 sharedEnchantment`partial apply for TwoStageCache.(objectForKey(URL, completion : (imgData : Data?, err : BBError?) -> ()) -> ()).(closure #1)
4 sharedEnchantment`thunk:

最佳答案

提前为这篇文章感到抱歉,但希望这些信息值得一读……

lldb 有两种查看变量的方式(*):printframe variable .
print并不是真正主要用于打印变量 - 这只是它真正作用的副作用。 printexpression 的别名这让您更了解它是什么:一个完整​​的表达式评估器,它运行您在代码中停止的位置传递的表达式。

它构建了一个上下文来模拟当前 pc 上的代码(包括类/协议(protocol)上下文),然后获取您传递给它的代码片段,在该上下文中编译它,JIT 是结果,将 JIT 代码插入到您所在的进程中调试并运行它。这是非常强大的 - 您可以更改值,在程序中调用函数,引入新函数、新类型等。但是也有很多机制只是为了让它运行,而且这些机制中的一些很难做到正确.
frame variable只能打印当前帧中的局部变量和参数(使用 -g 标志,它还可以打印全局变量和静态变量)。它不能调用函数或任何其他花哨的东西 print可以做。它确实理解变量访问语法的有限子集,因此:

(lldb) 框架变量 foo.bar.baz

将工作。但在幕后,它需要做的就是读取调试信息以找到变量、它的类型以及它在内存中的位置,然后它可以从该信息中提取值。因此,它所做的工作更快、更健壮——这是人们通常要求的工作的很大一部分print去做。

请注意,您可以通过 frame variable 为您访问的变量获得“对象打印”。通过使用 -O标志,它支持与 print 相同的结果格式选项。 .对于上下文,Xcode“Locals” View 大致相当于调用 frame variable .

我倾向于使用 frame variable用于简单的本地打印,但即使您喜欢使用一个命令满足您的所有需求 - 这将是 print - 很高兴知道如果 print 有回退由于某种原因失败。

回到你的例子......

示例 1:其中一件事 print在 Swift 中所做的是将所有可见的局部变量引入到表达式的上下文中,因此它们可用于您的代码。示例 1 中的错误是因为无法实现其中一个局部变量 - 也许它是协议(protocol)一致性指定的唯一变量,我们无法弄清楚它到底是什么 - 所以我们未能构建上下文,这意味着解析或 JIT 步骤失败。 print代码对此类故障进行预扫描并忽略失败的本地人,但您发现了此扫描未命中的情况。
frame variable也可能无法打印 runOnce但由于它不依赖于当前上下文,因此无法执行此操作不会影响您打印其他变量的能力。

如果您可以重现此问题,即使您无法向我们提供该项目,我们通常也可以从 lldb 的调试日志中找出发生了什么。因此,将调试 session 驱动到打印将失败的程度,然后执行以下操作:

(lldb) log enable -f /tmp/lldb-log.txt lldb expr types

然后运行失败的表达式。然后获取该日志,并按照此处所述提交错误:

https://swift.org/contributing/#reporting-bugs

示例 2:activeNetworkRequests 是一个属性吗?这些要求我们调用“get”方法来访问它们,我看到了一些 lldb 没有发出正确调用属性 getter 的代码的情况。上面的日志将向我们展示发出的代码,我们或许可以从那里看出哪里出了问题。当然,如果你可以制作一个测试用例,你可以发送最好的错误,但这通常是不可能的......

(*) 对于 gdb 用户,这非常接近 info locals比。 print ...

关于swift - LLDB 无法检查变量(在 Xcode 中),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43783834/

37 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com