LLDB无法检查Xcode 8/9/Swift 3/4中的变量

Ant*_*hko 6 xcode lldb swift

特别是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 - 变量有问题,大概是为了举例2

更新2:

码:

Util.log("Returning \(key) from file cache", [.Caches])
Run Code Online (Sandbox Code Playgroud)

输出:

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
Run Code Online (Sandbox Code Playgroud)

(所以价值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.
Run Code Online (Sandbox Code Playgroud)

如果我们看一下崩溃:

(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)
Run Code Online (Sandbox Code Playgroud)

从:

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:
Run Code Online (Sandbox Code Playgroud)

Jim*_*ham 15

对于这篇文章提前抱歉,但希望这些信息值得一读......

lldb有两种查看变量的方法(*):printframe variable.

print并不是主要用于打印变量 - 这只是它真正起作用的副作用. print是一个别名,expression它让您更加了解它是什么:一个完整​​的表达式计算器,它运行您在代码中停止的位置传递的表达式.

它构建了一个上下文,模拟当前pc上的代码(包括类/协议上下文),然后获取传递它的代码片段,在该上下文中编译它,JIT的结果,将JIT代码插入到您正在处理的流程中调试并运行它.这是非常强大的 - 您可以更改值,调用程序中的函数,引入新函数,新类型等.但是还有很多机器只是为了让它继续下去,并且快速地使用一些这样的机器很难做到正确.

frame variable只能在当前帧中打印本地和参数(带有-g标志,它也可以打印全局和静态).它不能调用函数,或任何其他花哨的东西print都可以做.它确实理解变量访问语法的有限子集,因此:

(lldb)帧变量foo.bar.baz

将工作.但是在幕后,它需要做的就是读取调试信息以查找变量,类型以及它在内存中的位置,然后它可以从该信息中提取值.因此,它的功能更快,更强大 - 这是人们通常要求print做的大部分工作.

请注意,您可以frame variable使用-O标记为您访问的变量获取"对象打印" ,并且它支持与结果相同的格式设置选项print.对于上下文,Xcode"Locals"视图大致相当于调用frame variable.

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

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

示例1:printSwift中的一个功能是将所有可见的局部变量引入表达式的上下文中,因此它们可供您的代码使用.示例1中的错误是因为其中一个局部变量无法实现 - 可能它只是由协议一致性指定而我们无法弄清楚它到底是什么 - 所以我们无法构建上下文,这意味着解析或JIT步骤失败.该print代码对此类故障进行了预扫描并省略了失败的本地人,但您发现此扫描未命中的情况.

frame variable可能也可能无法打印,runOnce但由于它不依赖于当前的上下文,因此无法做到这一点不会影响您打印其他变量的能力.

如果您可以重现此问题,即使您无法向我们提供项目,我们也可以经常弄清楚lldb的调试日志中发生了什么.因此,将调试会话驱动到打印失败的程度,并执行以下操作:

(lldb) log enable -f /tmp/lldb-log.txt lldb expr types
Run Code Online (Sandbox Code Playgroud)

然后运行失败的表达式.然后获取该日志,并提交错误,如下所述:

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

示例2:activeNetworkRequests是属性吗?那些要求我们调用"get"方法来访问它们,我已经看到了一些lldb没有发出代码来正确调用属性getter的情况.上面的日志将向我们显示发出的代码,我们可以从那里告诉我出了什么问题.当然,如果你可以制作一个测试用例,你可以发送总是最好的bug,但这通常是不可能的......

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