How to Debug Applications with `gdb` on Arch Linux

How to Debug Applications with gdb on Arch Linux

Debugging is an essential skill in the software development process. When something goes wrong, it’s crucial to understand what, why, and where the issue occurred. One of the most powerful and widely-used debugging tools for C and C++ programs is the GNU Debugger, better known as gdb.

In this article, we’ll walk through how to use gdb to debug applications on Arch Linux, from setting up your environment to using practical debugging commands. Whether you’re troubleshooting a segmentation fault, examining stack traces, or stepping through code, this guide will help you gain confidence in using gdb.


What is gdb?

gdb is the GNU Project Debugger. It allows you to:

  • Pause a running program at a specific point (breakpoint)
  • Step through the code line by line
  • Inspect and modify variables
  • Analyze stack traces
  • Identify memory-related issues such as segmentation faults

gdb supports many programming languages, but it’s most commonly used with C and C++.


Installing gdb on Arch Linux

On Arch Linux, gdb is available in the official repositories. You can install it with the following command:

sudo pacman -S gdb

Once installed, you can confirm the version:

gdb --version

Preparing Your Program for Debugging

To use gdb effectively, your program must be compiled with debug symbols. These symbols provide additional information such as variable names and line numbers, which are essential for debugging.

If you’re using gcc or g++, add the -g flag during compilation:

gcc -g -o myprogram myprogram.c

Avoid using the -O2 or -O3 optimization flags during debugging, as they may optimize away variables or rearrange code in a way that makes debugging harder. If needed, stick with -O0.


Basic Usage of gdb

Starting gdb

To start debugging your program, simply run:

gdb ./myprogram

This opens an interactive gdb prompt.

You can also pass arguments to your program by using --args:

gdb --args ./myprogram arg1 arg2

Running the Program

Inside gdb, use the run command to start the program:

(gdb) run

If your program crashes or exits, gdb will report it and show the state of the application.


Setting Breakpoints

Breakpoints tell gdb to pause execution at a certain point. You can then examine the program’s state.

By function name

(gdb) break main

By line number

(gdb) break myprogram.c:42

Conditional breakpoints

(gdb) break myprogram.c:42 if x == 5

Listing breakpoints

(gdb) info breakpoints

Deleting breakpoints

(gdb) delete 1

Stepping Through Code

Once a breakpoint is hit, you can step through code.

Continue execution

(gdb) continue

Step to the next line (into function calls)

(gdb) step

Step over function calls

(gdb) next

Finish current function

(gdb) finish

Examining Variables

(gdb) print x

You can also print dereferenced pointers:

(gdb) print *ptr

Examine memory

(gdb) x/4xw &x

This command prints 4 words (w = 4 bytes) in hexadecimal (x) starting at the address of x.

List all local variables

(gdb) info locals

List all function arguments

(gdb) info args

Working with the Call Stack

When a program crashes (e.g., segmentation fault), the call stack provides crucial insights.

Display the current stack

(gdb) backtrace

Or for a full backtrace:

(gdb) backtrace full
(gdb) frame 0       # current frame
(gdb) frame 1       # caller

View source in a specific frame

(gdb) list

Debugging a Segmentation Fault

Here’s an example workflow:

  1. Compile the program with -g
  2. Run it with gdb ./myprogram
  3. Start the program inside gdb with run
  4. When it crashes, use backtrace to see the call stack
  5. Inspect variables to find the root cause

Example output:

Program received signal SIGSEGV, Segmentation fault.
0x0000555555555156 in do_something (ptr=0x0) at myprogram.c:42
42        int val = *ptr;
(gdb) print ptr
$1 = (int *) 0x0

Clearly, ptr is NULL, which explains the crash.


Attaching to a Running Process

You can also attach gdb to a running process:

  1. Find the PID:
ps aux | grep myprogram
  1. Attach gdb:
sudo gdb -p <PID>

You can now inspect variables, set breakpoints, or even modify execution live.


Using Core Dumps

Core dumps are memory snapshots taken when a program crashes. To use them:

  1. Enable core dumps:
ulimit -c unlimited
  1. Run your program until it crashes and generates a core dump (usually named core or core.<pid>)

  2. Load the core dump with gdb:

gdb ./myprogram core

Now you can analyze the crash post-mortem.


Helpful gdb Commands Cheat Sheet

CommandDescription
runStart the program
break [location]Set breakpoint
delete [breakpoint #]Delete a breakpoint
info breakpointsShow all breakpoints
nextStep to next line (skip functions)
stepStep into function
finishRun until function ends
print VARPrint variable
backtraceShow stack trace
frame NSwitch to stack frame N
listShow source code around current line
continueResume program execution
quitExit gdb

TUI Mode: Text-Based UI in gdb

gdb also has a built-in text-based interface that displays source code, assembly, and registers in a split view. To launch it:

gdb -tui ./myprogram

Inside gdb, you can toggle the layout:

(gdb) layout src

Use arrow keys to navigate, Ctrl+L to refresh, and Ctrl+X A to toggle TUI mode.


Debugging C++ Programs

For C++, gdb still works well, though name mangling can be an issue. Use nm or c++filt to demangle names if necessary.

Or, within gdb, use:

(gdb) set print demangle on

This will display human-readable C++ function and variable names.


Integrating with Editors and IDEs

For convenience, many editors offer gdb integration:

  • Vim/Neovim: Use plugins like vimspector or termdebug
  • Emacs: M-x gdb integrates gdb with a graphical frontend
  • VS Code: Use the C/C++ extension from Microsoft, and create a .vscode/launch.json for gdb debugging

Tips and Best Practices

  • Always compile with -g during development.
  • Don’t optimize with -O2 unless testing production behavior.
  • Use breakpoints selectively to narrow down the problem.
  • Learn to read stack traces—this skill saves a ton of time.
  • Save time by scripting gdb with command files (gdb -x script.gdb).

Conclusion

Debugging with gdb is a powerful way to understand what’s happening inside your programs. While the learning curve may seem steep at first, mastering gdb gives you deep insight and control over your code’s behavior.

On Arch Linux, getting started with gdb is easy due to the system’s simplicity and the availability of up-to-date development tools. Whether you’re chasing down a nasty segmentation fault or simply trying to understand a function’s behavior, gdb is your ally.

With practice, gdb will feel like second nature—helping you write better, more reliable, and bug-free software.