Xcode Lldb Error: Can't Print Out Swift Variable - Get "$_Lldb_Injected_Self.$_Lldb_Wrapped_Expr_X" Instead

Xcode lldb error: can't print out Swift variable - get $__lldb_injected_self.$__lldb_wrapped_expr_x instead

As a workaround you can print it in the lldb debugger using:

frame variable variablename

Also possible using shortened syntax for quicker typing

fr v variablename

Since XCode 10.2 an ever simpler lldb syntax is supported:

v variable

Update - new workarounds:

Print stack addresses:

v -L variablename

po like on stack frame variable.property

 v -o variablename.property

Swift like p

e unsafeBitCast(address, to: ClassName.self)

Update2 - new workaround applicable for Swift classes being wrappers of objc classes.

Example:

v response
(HTTPURLResponse) response = 0x0000000283ba7640 {

if v works^:

e -l objc -- (int)[0x0000000283ba7640 statusCode]
(int) $2 = 404

I'd appreciate reports what is actually helpful and works. Thanks.

More information on this kind of capabilities can be found here:
https://developer.apple.com/library/content/documentation/General/Conceptual/lldb-guide/chapters/C5-Examining-The-Call-Stack.html

LLDB fails to examine variables (in Xcode)

Sorry in advance for the essay, but hopefully the info will be worth the read...

lldb has two ways of looking at variables(*): print and frame variable.

print isn't really meant primarily for printing variables - that's just a side effect of what it really does. print is an alias for expression which gives you a little more sense of what it is: a full expression evaluator which runs the expression you pass at the point where you are stopped in your code.

It builds a context that emulates the code at the current pc (including the Class/Protocol context) and then takes the snippet you pass it, compiles it in that context, JIT's the result, inserts the JIT'ed code into the process you are debugging and runs it. That's quite powerful - you can change values, call functions in your program, introduce new functions, new types, etc. But there is also a lot of machinery just to get it going, and with swift some of this machinery is tricky to get right.

frame variable can only print locals and arguments in the current frame (with the -g flag it can also print globals & statics). It can't call functions, or any of the other fancy things print can do. It does understand a limited subset of the variable access syntax, so:

(lldb) frame variable foo.bar.baz

will work. But under the covers, all it needs to do is read the debug information to find the variable, its type, and where it is in memory, and then it can extract the value from that information. So it is faster and more robust for what it does do - which is a large percentage of the work people generally ask print to do.

Note, you can get "object printing" for variables you access with frame variable by using the -O flag, and it supports the same formatting options for results as print. For context, the Xcode "Locals" view is roughly equivalent to calling frame variable.

I tend to use frame variable for simple locals printing, but even if you like to use one command for all your needs - which will be print - it's good to know that there's a fallback if print is failing for some reason.

Back to your examples...

Example 1: one of the things print does in Swift is introduce all the visible local variables into the context of the expression, so they are available to your code. The error in Example 1 is because one of the local variables couldn't be realized - maybe it was a only specified by a protocol conformance and we couldn't figure out what it really was - so we failed building the context, which means the parse or JIT steps failed. The print code does a pre-scan for this sort of failure and omits failing locals, but you've found a case this scan misses.

frame variable would have probably also failed to print runOnce but since it doesn't depend on the current context, the inability to do that wouldn't have affected your ability to print other variables.

If you can reproduce this issue, even if you can't make the project available to us we can often figure out what's going on from lldb's debugging log. So drive the debug session to the point where the print is going to fail, and do:

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

then run the failing expression. Then grab that log, and file a bug as described here:

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

Example 2: Was activeNetworkRequests a property? Those require us to call the "get" method to access them, and I have seen a few cases where lldb doesn't emit the code to call the property getters correctly. The log above will show us the code that was emitted, and we might be able to tell from there what went wrong. Of course, if you can make a test case you can send with the bug that is always best, but that's often not possible...

(*)For gdb users this is pretty close to the info locals vrs. print...



Related Topics



Leave a reply



Submit