I am trying to learn to debug programs written in Crystal with GDB. Here is a sample:
class Demo
@array = [] of String
def bar(url)
ret = url.downcase * 2
if ret == "alsj"
return false
else
return ret
end
end
def do(foo)
@array.push(foo)
html = bar(foo)
puts "HI" # GDB breakpoint here
return html
end
end
a = Demo.new
puts a.do("HI")
I compiled the sample above with the --debug
flag and loaded it into GDB. Then I let it run and stopped at the marked line (GDB breakpoint here
). Now I have three four questions:
foo
):
When I inspect a string variable, I often see something like $1 = (struct String *) 0x4b9f18
. When I say printf "%s", foo
, I get nothing back. How can I display the current value of a string variable?$1 = <optimized out>
when inspecting a variable. What does that mean and how can I see the value in that case?@array
in the given situation? p array
says no symbol in current context and p @array
returns unknown address space modifier.
Edit: I found a way: use p self.array
puts "HI"
) I can't see the variable html at all: p html
returns no symbol in current context. Why is that and how do I solve it?Crystal debugging capabilities are still on development so you can't see some symbols or symbols data is optimized by LLVM. About optimized output, sometimes crystal algorithms are optimized too much, even on --debug
builds. By example:
Currently yield methods are inlined and optimized, so this isn't very debuggable.
3.times do |i|
pp i
end
However, you can use pp
keyword to print name => value
.
pp i
i => 1
i => 2
i => 3
Also you can set breakpoints using debugger
keyword and inspect macro output using {% debug() %}
or $ crystal tool expand
command.
On the other hand compound statement are easy to debug using tools like GDB.
i = 0
while i < 3
debugger
i += 1 # i variable is listed by GDB
end
Finally you can try some tricks I found in my debugging daily tasks.
@[NoInline]
and p &foo.c
this will enable args data and you will be able to print all struct string valueUsing @[NoInline]
attribute:
@[NoInline]
def do(foo)
debugger
end
On GDB:
(gdb) p &foo.c
$1 = (UInt8 *) 0x10008e6c4 "HI"
optimized out: maybe because LLVM optimizes some method calls. if you see <optimized out>
use @[NoInline]
and try assigning instance vars to local vars array = @array
Accessing object variables: use self.var
for instance vars.
Also use p array.buffer[0]@size
to print array values.
(gdb) p &array.buffer[0].c
$19 = (UInt8 *) 0x10008e7f4 "HI"
Try adding debug info manually converting or casting values:
@[NoInline]
def do(foo)
html = bar(foo).as(String)
html = bar(foo).to_s
debugger
end
Now html var is visible on GDB thanks to .as
or .to_s
methods
(gdb) p &html.c
$1 = (UInt8 *) 0x1002fcfec "hihi"
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With