Debug a Vala or C App

How to effectively debug Vala or C code.

This page mainly focuses on debugging in the Terminal. If you want to setup a graphical environment for Vala development and debugging, please have a look at Vala Development in VSCode.

If you like my work, ❤️ Sponsor Me. It would mean the world to me!

Enable Debug Output

Set the environment variable G_MESSAGES_DEBUG to all to get all log messages printed to stdout:

G_MESSAGES_DEBUG=all com.github.marbetschar.my-app

Or if the app in question is a Flatpak app, you'll need to start the app with flatpak run:

G_MESSAGES_DEBUG=all flatpak run com.github.marbetschar.my-app

Using GNU Debugger

Installing GNU Debugger

sudo apt install gdb

Retrieve a backtrace (e.g. to debug a Segmentation fault)

Run the program in question with GNU Debugger:

$ gdb com.github.marbetschar.my-app
...
Reading symbols from com.github.marbetschar.my-app...
...
# Now type `run` and hit enter to start the app:
(gdb) run

Once the application crashes you should see a message similar to the following:

Thread 1 "executable" received signal SIGSEGV, Segmentation fault.
0x00007ffff709b434 in my_function_in_which_the_code_crashed () from /lib/x86_64-linux-gnu/libxyz-1.6.so.62
(gdb)

To retrieve a backtrace at this state, simply execute the backtrace command:

(gdb) backtrace
#0  0x00007ffff709b434 in my_function_in_which_the_code_crashed () at /lib/x86_64-linux-gnu/libxyz-1.6.so.62
#1  0x00005555555962ef in my_previously_executed_function (node=0x7fffffffcbc0, highest=1537725293) at ../src/MyCode/UsefulStuff.vala:168
...
# Now type `quit` and hit enter to exit:
(gdb) quit

Retrieve a backtrace for a warning or critical message

In this case you want to abort the program as soon as a warning or critical message is logged. To do so, the G_DEBUG environment variable comes in handy:

# Causes GLib to abort the program at the first call to g_warning()
# or g_critical(). Use of this flag is not recommended except when
# debugging:
export G_DEBUG=fatal-warnings

# Causes GLib to abort the program at the first call to g_critical().
# This flag can be useful during debugging and testing:
export G_DEBUG=fatal-criticals

Once the environment variable is set, it causes the application to crash at the desired place. You are then able to retrieve a backtrace as described above.

Using core dumps

You can let Linux automatically collect the required information for a backtrace whenever an application crashes unexpectedly. This information is stored in a so called "core dump" file which contains the recorded state of the complete memory from the crashed application. Those core dumps are especially useful for errors which occur seemingly at random, because you don't need to explicitly start the application using GNU Debugger and you are still able to retrieve a backtrace after a crash.

Please be aware that core dumps may contain sensitive information due to their very nature: They are really just a copy of the app's memory at a given point in time. This may or may not include sensitive information such as passwords etc.

Installing systemd-coredump

sudo apt install systemd-coredump

List existing core dumps

$ sudo coredumpctl list
TIME                            PID   UID   GID SIG COREFILE  EXE
Fri 2021-05-14 18:57:59 CEST 181233  1000  1000  11 missing   /path/to/executable
Sun 2021-05-16 15:03:01 CEST   3258  1000  1000  11 present   /path/to/other-executable
Mon 2021-05-17 17:23:30 CEST  61215  1000  1000  11 present   /path/to/executable

Debug existing core dump

$ sudo coredumpctl debug /path/to/executable
...
(gdb) backtrace
#0  0x00007ffff709b434 in my_function_in_which_the_code_crashed () at /lib/x86_64-linux-gnu/libxyz-1.6.so.62
#1  0x00005555555962ef in my_previously_executed_function (node=0x7fffffffcbc0, highest=1537725293) at ../src/MyCode/UsefulStuff.vala:168
...
(gdb) quit

Further Reading

Last updated