Debugging
Stack traces, debug builds, and a debugger.
On this page
Every panic names the file and line it came from. A debug build adds a stack trace and the information a debugger such as gdb or lldb needs.
Panic messages#
fn pick(items: Array[int], index: uint) int {
return items.get(index) !!
}
fn main() {
let items = Array[int]{ 1, 2 }
println(pick(items, 5))
}
Unhandled error 'LookupError.missing' at src/main.valk:2
panic("message"), an error left unhandled by !!, an index out of bounds and a division by zero all print a message with the location, relative to the package root, and exit with status 1. A location inside a library ends with in package <name>.
Debug builds#
valk build src -d -o app
With -d (or --debug), a panic also prints every call that led to it:
Unhandled error 'LookupError.missing' at src/main.valk:2
Stack trace:
at main.pick (src/main.valk:2)
at main.main (src/main.valk:7)
A crash, such as a segmentation fault or a stack overflow, prints the trace too. Debug builds are slower and use more memory, so don't ship them.
Use a debugger#
A debug build carries DWARF debug info (a .pdb file on Windows), so gdb, lldb and Visual Studio show functions, source lines, arguments and local variables.
valk build src -d -o app
gdb ./app
(gdb) break main.valk:2
(gdb) run
Breakpoint 1, main.pick (items=0x5555555a7348, index=5) at src/main.valk:2
(gdb) print index
$1 = 5
(gdb) bt
Functions appear as namespace.name, such as main.pick, and methods as Type.method, so break main.pick works as well as a file and line.
