Lets say I have a small program that involves picking a document from a database:
let errorDatabase
= NSError(domain: "dk.myproject.couchbase", code: 0, userInfo: nil)
let rev = database.existingDocumentWithID("_design/" + designDocName)
// in xcode I set a break point here
assert(rev != nil)
if rev == nil {
promise.failure(errorDatabase)
}
Then I insert a breakpoint, run the program and can afterwards do:
(lldb) po rev
0x00007fad21df61c0
{
ObjectiveC.NSObject = {...}
}
(lldb) print rev.properties["views"]
(AnyObject?) $R29 = Some {
...
Perfect lets enter the repl and play with the rev object:
(lldb) repl
6> rev
repl.swift:6:1: error: use of unresolved identifier 'rev'
rev
^
I might have wrong expectations for the swift repl - I'm expecting some kind of python, nodejs or scala repl. behaviour where I can play around with objects etc.
Any hints?
I was hoping the same thing the first time I typed repl within LLDB, but I soon discovered that unfortunately you can't do it.
The repl inside LLDB, it turns out, is running in a module injected at top level. Thus you could, from within the repl here, define top-level objects and functions, which are then visible back in "normal" lldb:
(lldb) repl
1> func pt() -> CGPoint {
2. return CGPointZero
3. }
4> :
(lldb) po pt()
(0.0, 0.0)
... but the converse is not true: you cannot, inside the repl, see local variables at the point you are paused, as they are obviously not in scope from top level.
Do note, however, that you can perform assignments in an expr expression. Thus, you can change the value of a local variable, the properties of an existing object, etc., just by saying expr followed by an assignment - and that this does take place in the context where you are paused.
For example, let's say I'm in the middle of creating a pan edge gesture recognizer, and I pause at a breakpoint at this line:
p.edges = UIRectEdge.Right
Now:
(lldb) th step-over
(lldb) expr p.edges = UIRectEdge.Left
(lldb) continue
And now the app is running, but the gesture recognizer works when swiping from the left instead of the right.
Note, I described the purposes and differences between "expression" and "repl" in this question:
Xcode 6.1 'Swift REPL built into the Xcode debugger can inspect and manipulate your running app' not working
Maybe that will help you understand the similarities & differences you are seeing and then intent behind them.
Related
While Coding in Python, I often do something like
test.py
x = []
breakpoint()
± |master U:5 ?:4 ✗| → python3 test.py
-> breakpoint()
(Pdb) x
[]
(Pdb) x.append(1)
(Pdb) x
[1]
Is it possible to execute the statement while debugging Rust?
use std::collections::HashMap;
fn main() {
let mut contacts = HashMap::new();
contacts.insert("Daniel", "798-1364");
contacts.insert("Ashley", "645-7689");
//set breakpoint here
}
So far, I can execute p contacts in the debug console, the meaning of this output isn't straight to me. What if I want to know the outcome of println!("{:?}", contacts); without writting this line of code in the source file.
And also I want to know the outcome of contacts.insert("Robert", "956-1742"), If I execute expr contacts.insert("Robert", "956-1742") in the debug console, it says error: no field named insert.
Rust debugging support is currently quite limited with both lldb and gdb. Simple expressions work, anything more complex is likely to cause problems.
My experience while testing this with rust-lldb:
The expression parser only understands a limited subset of Rust. Macros are not supported.
Functions that are not used are not included in the resulting binary. E.g. you cannot call capacity() on the HashMap in the debugger since that function is not included in the binary.
Methods have to be called like this: struct_value.method(&struct_value)
I haven't found a way to call monomorphized methods on generic structs (like HashMap).
String constants "..." in lldb expressions are created as C-style string constants, e.g. "abcdef" is a const char [7] including the trailing NUL byte. Thus they cannot be easily passed to Rust functions expecting &str arguments.
Trying to use a helper function like this:
pub fn print_contacts(contacts: &HashMap<&str, &str>) {
println!("{:?}", contacts);
}
causes lldb to crash:
(lldb) expr print_contacts(&contacts)
PLEASE submit a bug report to https://bugs.llvm.org/ and include the crash backtrace.
Stack dump:
0. Program arguments: [...]
Segmentation fault: 11
So it seems that what you want to do is not possible at this time.
I'm trying out generics in swift an came across something unusual while debugging:
instead of printing out the value assigned to the variable, it just prints something different. Heres the example code:
class GenericExample<T: Comparable>{
var someVar: T
init(myVar: T){
someVar = myVar
}
}
let generics = GenericExample<Int>(myVar: 57)
print(generics.someVar)
the result is fine(57) but when running the program for debugging, as in with breakpoints, the value is presented as something like 4301684792
any tips would be appreciated
Don't examine, in the debugger, the value of a variable whose value is not assigned until the line you're breakpointed in or later. That line has not been executed yet, so you will see a random value! (Namely, whatever happens to be sitting in memory at that address.)
Only examine earlier variable values! And don't even look at the little tooltips that pop up. Look only at the variables pane and the lldb console.
Why does lldb insist on printing the wrong data — the value of the first ivar, no matter which ivar I ask for? This is Xcode 5.1.1. And yes, I am compiling with -O0, symbols not stripped, etc.
(lldb) print *self
(SMTestHarness) $13 = {
NSObject = {
isa = SMTestHarness
}
_dir = 0x00740520 #"/Users/lc/Projects/servermonitor/Test/unit-test"
_ip = 0x007406b0
_domain = 0x007429f0
_sm = 0x00676900
_state = 0x00741980
_dsaSimulators = 0x00741d10 5 key/value pairs
_timers = 0x00741f50 2 objects
_originalWd = 0x007403f0 #"/Users/lc/Projects/servermonitor/Test"
}
(lldb) print _dir
(NSString *) $14 = 0x00740520 #"/Users/lc/Projects/servermonitor/Test/unit-test"
(lldb) print _ip
(IPAddress *) $15 = 0x00740520
(lldb) print _domain
(FirstPointDomain *) $16 = 0x00740520
(lldb) print _sm
(ServerMonitorCrashTestDummy *) $17 = 0x00740520
Interestingly, the variable display in the left-hand pane is correct; it's only print commands in the lldb console that are wrong.
The variables view in Xcode doesn't use the lldb expression parser (i.e. the print command.) Mainly this is because it would be very inefficient to have to parse expressions for each local variable & its subelements every time you step. And even without this, a full-on expression parser is way more fire power than you need for the task of dumping local variable values.
Instead, lldb has another sub-system just for dumping the contents of variables (no calling functions or complex expressions, just printing values.) From command-line lldb, you can get at that subsystem with the frame variable command.
That bit of trivia probably doesn't help you much, but it is why you can get different results from "print" which runs the fully general expression parser and the Xcode locals view...
What you are seeing, however, is that the lldb expression parser isn't getting the value of the offsets of individual ivars within their containing ObjC object right. The expression parser thinks all the ivars are at 0 offset from the object start - which is in fact what your example shows. And more particularly - from the example you included - this happens when debugging a 32 bit app using the 1.0 version of the Objective C Runtime.
That's a long-standing bug in lldb.
There isn't a good workaround if you have to debug ObjectiveC 1.0 32-bit x86 apps. If you have a 32 bit only machine, then you are pretty much stuck here, and have to use frame var. But if you have a 64-bit capable machine, unless there's some very compelling reason to debug the 32 bit fork of the app, you can just switch to debugging the 64 bit version of the app instead, and this problem should go away.
Note, though the iOS simulator runs 32 bit code, it uses the ObjectiveC 2.0 runtime, and doesn't have this bug.
If you are printing objects use the "po" (print object) command.
It seems reasonably widely acknowledged that it is slow to use the po command in Xcode 4.6.x. What are the options for inspecting the values of arbitrary variables unspecified at compile time (which rules out usage of NSLog()) which don't take > 15s?
Just set a breakpoint where you want to learn the variables' value. Once the program is paused, a summary of all the variables' value will appear on the Varibles view on the left-bottom of the screen. Here is a screenshot :
You can use the lldb commands:
p (int) myInt
po myObject
po myObject.memberObject
p (float) myObject.floatMember
Just a note, you could also use p instead of po in the newest version of Xcode. If you run the help -a in llb, it will present you with command aliases, below is a snippet of the commands you could use.
> (lldb) help -a
p -- ('expression --') Evaluate a C/ObjC/C++ expression in the current
program context, using user defined variables and variables
currently in scope.
po -- ('expression -o --') Evaluate a C/ObjC/C++ expression in the
current program context, using user defined variables and
variables currently in scope
print -- ('expression --') Evaluate a C/ObjC/C++ expression in the current
program context, using user defined variables and variables
currently in scope.
Turns out the answer is pretty simple: download Xcode 4.6.2 where LLDB debugging speed has been increased significantly. Note some discussion over here
Is it possible to detect when the value of a variable has changed using the lua debug library.
Something like A callback function which would give details like the function in which the value was changed, previous value, etc.
Is such a thing possible?
I read about hooks, but I'm not sure hooks can be set to variables.
If you don't mind using a debugger, then some debuggers allow you to set Watch expressions, which will be triggered when the condition in the expression is true. I'll show how this can be done in MobDebug (it is using lua debug library, but there is no direct way to detect a variable change as far as I know).
Let say we have a script start.lua like the one below and want to detect where foo gets value 2:
print("Start")
local foo = 0
for i = 1, 3 do
local function bar()
print("In bar")
end
foo = i
print("Loop")
bar()
end
print("End")
Download mobdebug.lua and make it available to your scripts (the simplest way is to put it into the folder with your scripts).
Start the server using lua -e "require('mobdebug').listen()" command.
Start the client using lua -e "require('mobdebug').loop()" command.
You will see the prompt in the server window: '>'. Type load start.lua to load the script.
Type step and then step again. You will see "Paused at file start.lua line 3".
Let's see what the value of foo is. Type eval foo and you should see 0.
Now we can set up our watch. Type setw foo == 2. You can specify any Lua expression after setw command; the execution of your script will be stopped when the condition is evaluated as true.
Continue execution of the script using "run" command.
The watch now fires, which will show you the message like: "Paused at file start.lua line 8 (watch expression 1: [foo == 2])". This means that the previous expression changed the value of foo to 2 and the execution is stopped at line 8. You can then inspect your script and the current values (you can use "eval" and "exec" commands to run any Lua code to be evaluated in your script environment) to find what triggered the change.
The benefit of this approach is that you are not limited to monitoring table values and can specify any expression. The main disadvantage is that your script runs under a debugger and the expression is evaluated after each step, which may get really slow.
You can do this to a certain extent in Lua by using metatables and keeping a "proxy" table, and using the __newindex function call to detect attempts to add a variable.
This is covered here in the Programming in Lua book under the section "Tracking Table Accesses":
http://www.lua.org/pil/13.4.4.html
See Also
http://www.gammon.com.au/forum/?id=10887