I am new to Xcode and came by pycharm. In pycharm, I am able to use watcher to execute the statement and store as local variable in debugger mode. How could I do that same thing from Xcode debugger lldb?
for example
let a = 5
letba = 5
let aPlusb = Self.addFunc(a, b)
after place debugger on line 3. how can i call Self.addFunc() and store into some variable xy
I have tried expression or e under lldb and then po xy but it does not work with error
error: expression failed to parse:
error: <EXPR>:8:1: error: cannot find 'xy' in scope
`xy`
You're right that the expression parser is the command you want to use to create scratch variables that can record values in lldb. There are two ways to do this.
First of all, when you evaluate any expression using lldb's expression parser, lldb creates a "result variable" which stores the result of the expression:
(lldb) expr myVar
(Int) $R0 = 10
This can be used in future expressions, e.g.:
(lldb) expr print($R0)
10
The other way you can do this is to take advantage of the lldb convention that an identifier in an lldb expression which begins with a $ is treated as an lldb "persistent declaration", and can be used in future expressions. Except for a very few exceptions like this, lldb parses expressions exactly as they would be in source code compiled in the context of the current frame. So you just use the same syntax you would use to define the identifier in swift, so:
(lldb) expr var $myVar = 10
(lldb) expr print($myVar)
10
BTW, I'm not being abstruse using "identifier" instead of "variable" above. The same convention holds for other instances of identifiers, e.g. for type and function definitions as well.
Related
I'll start with my code:
macro example(args...)
local s = __source__
println(s) # This part works, showing macro is called on line 9
quote
println(s) # Julia tells me this variable "s" is not defined
println(__source__) # Likewise, "__source__" is not defined here either
end
end
#example 42 # Line 9 of my file
In my macro above I want to record the line number that is calling the macro and use it within my quote block. Both capturing it in a variable outside the quote block and using it within, or using it directly in the quote block don't work. My understanding is the code outside the quote block runs at parse-time, and the expression returned from the quote block is evaluated at run-time.
I feel like there must be a way to capture that variable and inject it right into the expression that will be evaluated later, but I haven't figured out how to do that. Any help here is appreciated. If there is a better way to do this let me know.
I ended up finding out an answer on my own. In the second line if I changed __source__ to __source__.line or __source__.file it worked fine as long as I then used $ to interpolate the result into the expression the macro returned. I'm still not sure why __source__ on its own didn't work, but using either .line or .file methods is working for me now.
I'm experiencing a similar problem trying to use __source__.
I think I can offer insight into why source.line, etc worked though.
The value of source.line is an integer. The value of source.fike is a string. Numbers and strings evaluate to themselves.
A symbol, on the other hand, evaluates to whatever value it has in the environment.
Trying to pass a large string to a shell script using a breakpoint in Xcode
let value = Array(repeating: "a", count: 1500).joined()
let string = "{\"key\": \"\(value)\"}"
Unfortunately, the string is being truncated. Is this limitation documented and can it be overcome?
It's been nearly a year since you asked this, and I'm not sure if it will solve your question, but I've recently had a similar problem so thought I'd share my solution.
I had two issues:
LLDB was truncating any arguments to my shell script (and string variables printed in the console using po foo) to 1023 characters. I believe this is the issue to which your question relates.
Xcode was incorrectly confusing a comma , in my string as a separator for multiple arguments (e.g. passing foo, bar, and baz as arguments to the script wouldn't work correctly if any of the variables contained a , as Xcode would try to create another argument).
So, firstly, the LLDB issue...
It seems that by default LLDB has a limit on the character length that it will print to the console (or pass to a shell script via a breakpoint argument) of around 1023 characters. You can easily change this to something larger by setting another breakpoint before the breakpoint that uses your variable and running (lldb) set set target.max-string-summary-length 10000 in the console. This can be a bit annoying so I created a ~/.lldbinit file and placed set set target.max-string-summary-length 10000 in there instead so I don't have to keep setting it in the console.
Secondly, the comma issue...
Inside the Edit breakpoint... menu that you provided a screenshot of above there is the option to not only provide a path to a script but to also provide arguments. I can see from your question that you provided the argument #string#. For my script, I was passing multiple arguments, which Xcode allows you to do using a comma separated list, e.g. #foo#, #bar#, #baz#. Each of these arguments was a string.
I noticed that sometimes one or more of these strings would truncate if they contained a comma: ,.
So the string:
{ "num_friends" : "7" }
would be passed to my script as expected. But the string:
{ "num_friends" : "7", "num_deleted_friends" : "1" }
would truncate and would be passed to my script as two separate arguments. It seems that Xcode would split any string with a , even when entered using #string#.
I validated this in my script by simply using something like:
for var in "$#"
do
echo "$var"
echo "===="
done
Where $# expands to contain each argument. From this I could see that #string# was being correctly passed to my script but separated as multiple arguments wherever there was a ,. So if #string# contained a comma my script would print:
#"{ \"num_friends\" : \"7\"
====
\"num_deleted_friends\" : \"1\" }"
instead of what I expected which was:
#"{ \"num_friends\" : \"7\", \"num_deleted_friends\" : \"1\" }"
So it seems like it might be a bug in how Xcode passes strings inside # expressions in the breakpoint editor window.
My crude solution has been to just replace any commas with another character and then replace them back again inside my script. There's probably a better way to do this but I don't require it for my needs.
When i try to evaluate line 2 or 5 of this program, i get "Unbound value carre" or "Unbound value bis".
To evaluate it i use emacs with tuareg, could it be related ?
let carre x = x*x;;
carre(9);;
let bis y = y^y;;
bis("ab");;
For example, here is what i get for line 2 :
# Characters 0-5:
carre(9);;
^^^^^
Error: Unbound value carre
#
The code is very simple so i feel like the problem comes from emacs.
I've tried to change function names, variables names, but nothing worked.
Does anybody see what's wrong here ?
You need to evaluate the first line of your program before the second.
The interpretor doesn't know the definition of carre or bis until you've evaluated it.
I am currently trying to create dynamic variable names based on the valuelabels of the passed Argument. Currently, I have something like this:
COMPUTE counter = 0.
APPLY DICTIONARY FROM *
/SOURCE VARIABLES = V601
/TARGET VARIABLES = counter.
DEFINE !macro1 (!POS !CMDEND).
STRING name (A20).
!DO !#i = 1 !TO 62
COMPUTE counter = #i
!IF (!POS !EQ !i)
!THEN
COMPUTE name = VALUELABEL(!POS)
COMPUTE !CONCAT('wasnot', name) = 1.
!ELSE
COMPUTE name = VALUELABEL(!counter).
COMPUTE !CONCAT('wasnot', name) = 0.
!IFEND
!DOEND
CROSSTABS v15 by !CONCAT('wasnot', name) /cells = column.
!ENDDEFINE.
The idea is, that for every unique value of V601 a flag variable will be created (e.g. "wasnotvaluelabel1"). This variable will either have value = 1 or 0 respectively. However, it seems that concat cannot be used the way I intended. I get these errors:
Error # 6843 in column 7. Text: !POS
The end of a macro expression occurred when an operand was expected.
Execution of this command stops.
Error # 6846 in column 7. Text: !POS
A macro expression includes an undefined macro variable or a macro operator
which is not valid within an expression.
Error # 6836 in column 12. Text: !EQ
In a macro expression, an operator was not preceded by an operand.
Error # 6846 in column 2. Text: !THEN
A macro expression includes an undefined macro variable or a macro operator
which is not valid within an expression.
Error # 6846 in column 28. Text: !POS
A macro expression includes an undefined macro variable or a macro operator
which is not valid within an expression.
Questions I have right now:
Is it even possible to generate dynamic names? I have tried
different attempts over the last hours but the SPSS macro "language"
seems very restricted.
Is there perhaps some other way to achieve this Task? It seems rather unconvenient.
Please note, working with the Python AddIn is sadly not an Option. I'm grateful for any received advice.
There is an extension command, SPSSINC CREATE DUMMIES, that will create all these dummy variables automatically. It's on the Transform menu. And it is implemented in Python.
Using Python you can easily read case data and do lots more.
Thanks for all the Help. In the end I did it with generating new syntax using Outfile.
having a code like this:
var foo: Int = 0
print (foo)
With a breakpoint at the print line... then doing:
(lldb) exp foo = 7
(lldb) p foo
(Int) $R2 = 7
0
print(x) still returns 0 instead of 7. How is that possible?
More details would help, but in general, I have seen this happen in three cases:
1) When you have a let, the compiler is free to replace the let with its value. This is not your case, but for sake of argument, given:
let x = 0
print(x)
The compiler is free to rewrite this as
print(0)
leaving the let binding in only for the sake of the debugger. Now, a let is a let, so writing to it is not exactly a well-defined operation. With that said, C compilers seem to not take that same kind of approach with const values, so that failure mode might surprise somebody
2) If you call a function, the compiler is (essentially) going to emit code to push the arguments on the stack, and then jump to the code for the function. In theory, one would expect the line table in the debug info to guide the debugger to stop before the arguments are pushed. Then,
>> push x
call print
A write to x would actually "mean" something in the context of your print call. But, if the line tables actually make us stop at the call, even if you write to "x", it has already been pushed, and the old value will be used
3) The compiler might actually be using a copy of "foo" that is in a register, but for the sake of debug info, pointing us to a stack copy of "foo" which is actually never used, and only updated when writes to "foo" happen. If that is the case, LLDB will gladly write to the stack, but that won't affect the program's behavior as it is not actually reading from the stack
Fun things to try to figure this out include:
the LLDB disassemble command
(lldb) reg read pc
(lldb) dis -s <value of program counter>
or
(lldb) fr var -L foo
and then read at the memory address (or the register) that LLDB gives out as the location of "foo"
or
in your app, print(x) twice, and see if the second print shows a different value