Crystal Debug
This tutorial has tips and tricks on how to debug Crystal projects. It shows how to leverage tools like GDB or LLDB using debugger clients like Native Debug for VSCode.
- GNU debugger (GDB) or LLVM debugger (LLDB) - See installation guide below
Install
gdb
or lldb
accordingly to your OS.Confirm that the above prerequisites are installed before setting up the debugger. These settings have been verified for mac OS and Linux environments.
By convention the project directory name is the same as your application name, if you have changed it, please update
${workspaceFolderBasename}
with the name configured inside shards.yml
{
"version": "2.0.0",
"tasks": [
{
"label": "Compile",
"command": "shards build --debug ${workspaceFolderBasename}",
"type": "shell"
}
]
}
{
"version": "0.2.0",
"configurations": [
{
"name": "Debug",
"type": "gdb",
"request": "launch",
"target": "./bin/${workspaceFolderBasename}",
"cwd": "${workspaceRoot}",
"preLaunchTask": "Compile"
}
]
}
{
"version": "0.2.0",
"configurations": [
{
"name": "Debug",
"type": "lldb-mi",
"request": "launch",
"target": "./bin/${workspaceFolderBasename}",
"cwd": "${workspaceRoot}",
"preLaunchTask": "Compile"
}
]
}

debugging
Fully debugging Crystal applications is not supported yet. You can use some of the techniques below to improve the debugging experience.
Instead of putting breakpoints using commands inside GDB or LLDB you can try to set a breakpoint using
debugger
keyword.i = 0
while i < 3
i += 1
debugger # => breakpoint
end
Currently, Crystal lacks support for debugging inside of blocks. If you put a breakpoint inside a block, it will be ignored.
As a workaround, use
pp
to pretty print objects inside of blocks.3.times do |i|
pp i
end
# i => 1
# i => 2
# i => 3
Sometimes crystal will optimize argument data, so the debugger will show
<optimized output>
instead of the arguments. To avoid this behavior use the @[NoInline]
attribute before your function implementation.@[NoInline]
def foo(bar)
debugger
end
To print string objects in the debugger:
First, setup the debugger with the
debugger
statement:foo = "Hello World!"
debugger
Then use
print
in the debugging console.(gdb) print &foo.c
$1 = (UInt8 *) 0x10008e6c4 "Hello World!"
Or add
&foo.c
using a new variable entry on watch section in VSCode debugger
Using VSCode GUI
To print array items in the debugger:
First, setup the debugger with the
debugger
statement:foo = ["item 0", "item 1", "item 2"]
debugger
Then use
print
in the debugging console:(gdb) print &foo.buffer[0].c
$19 = (UInt8 *) 0x10008e7f4 "item 0"
Change the buffer index for each item you want to print.
For printing
@foo
var in this code:class Bar
@foo = 0
def baz
debugger
end
end
Bar.new
You can use
self.foo
in the debugger terminal or VSCode GUI.Some objects do not show at all. You can unhide them using the
.to_s
method and a temporary debugging variable, like this:def bar(hello)
"#{hello} World!"
end
def foo(hello)
bar_hello_to_s = bar(hello).to_s
debugger
end
foo("Hello")
This trick allows showing the
bar_hello_to_s
variable inside the debugger tool.Last modified 6mo ago