Master GDB: Essential Debugging Techniques for C/C++ Developers
This comprehensive guide explains what GDB is, how to launch it, its core functions, essential debugging commands, multithreaded debugging strategies, and practical code examples, helping developers efficiently locate and fix bugs in C/C++ programs.
1. GDB Debugging Tool
GDB (GNU Debugger) is a powerful debugging tool that helps developers quickly locate and resolve program bugs.
GDB performs four main tasks:
Specify variables or conditions that affect program behavior before it starts.
Pause the program at a specified location or condition.
Inspect what has happened when the program stops.
Modify variables or conditions during execution to test bug fixes and continue debugging.
Starting GDB gdb: start GDB alone; use file or exec-file to specify the program. gdb test.out: directly load and debug test.out. gdb test.out core: analyze a core file generated after a crash.
Dynamic attachment
Use gdb test.out pid to attach to a running process (obtain pid via ps aux).
Compile programs with gcc -g to embed debugging information.
2. GDB Debugging Techniques
Conditional breakpoints
Set with break 666 if testsize==100123123 to stop only when a condition is met.
Breakpoint commands
Scripts can be attached to breakpoints to print variables, check conditions, etc.
Memory dump
Use x/16xw 0x7FFFFFFFE0F8 to display 16 words in hexadecimal; custom hexdump commands are also available.
Inline disassembly
Commands disassemble or disas show the assembly for a function, e.g., disas main.
Reverse debugging
Available in GDB 7.0+, use reverse-continue ( rc) or reverse-step ( rs) to run the program backwards.
3. GDB Debugging Methods
Compile and start debugging
Compile with gcc -g main.c -o test.out. Start with gdb test.out and run via run. To debug a running program, find its PID and use gdb attach pid or gdb -p pid.
Debugging commands list: show source code (default 10 lines). break: set breakpoints (by line, function, file:line, or condition). next ( n): execute next line without entering functions. step ( s): step into functions. continue ( c): resume execution until next breakpoint. print / display: show variable values (formats: x, d, u, o, t, c, f). watch, rwatch, awatch: monitor variable changes.
Segmentation fault debugging
Generate a core file with ulimit -c unlimited, then load it via gdb program core. Use backtrace, frame, and print to locate the fault.
4. Other GDB Tips
4.1 Debugging parameters
Common commands: gdb [executable] – start GDB. break [line|function|file:line] – set breakpoints. info breakpoints – list breakpoints. delete breakpoints [num] – remove breakpoints. disable/enable [num] – pause/activate breakpoints. clear [line] – clear a breakpoint.
4.2 Viewing memory
Use x/<n/f/u> <addr> where n is length, f format (x, d, u, o, t, c, f, i, a), and u unit size (b, h, w, g).
4.3 Viewing source
Use list, list 12, or list functionName to display source around a line or function.
4.4 Stack frame commands
info frame– detailed frame info. up / down – navigate frames. info locals – show local variables.
5. GDB Multithreaded Debugging
5.1 Basics
Set breakpoints with break function_name, view threads via info threads, switch threads with thread thread_id, and watch variables with watch variable_name.
5.2 Multithreaded program compilation
#include <stdio.h>
#include <pthread.h>
#define NUM_THREADS 5
void * thread_func(void * thread_id) {
long tid = (long)thread_id;
printf("Hello World! It's me, thread #%ld!", tid);
pthread_exit(NULL);
}
int main() {
pthread_t threads[NUM_THREADS];
int rc;
long t;
for (t = 0; t < NUM_THREADS; t++) {
printf("In main: creating thread %ld", t);
rc = pthread_create(&threads[t], NULL, thread_func, (void *)t);
if (rc) {
printf("ERROR; return code from pthread_create() is %d", rc);
return -1;
}
}
pthread_exit(NULL);
}Compile with gcc -g -pthread -o multithread multithread.c.
5.3 Debugging steps for a simple multithreaded program
Compile: gcc -g -pthread -o simple_thread simple_thread.c.
Start GDB: gdb simple_thread.
Set breakpoint at main: break main.
Run: run.
Use info threads to list threads.
Switch with thread thread_id and step using next.
5.4 Advanced multithreaded debugging
Set breakpoints on synchronization functions, use info threads to monitor thread states, and thread apply all bt to view all call stacks. Conditional breakpoints help isolate issues in complex interactions.
5.5 Thread locking and concurrency control
Use set scheduler-locking on|step|off to control which threads run during stepping.
5.6 Command combinations for efficient debugging
info threads + thread thread_id + bt– view a specific thread’s stack. break function_name if condition + run + next/step – conditional break and step. thread apply all command – execute a command on all threads.
5.7 Common issues
Deadlocks can be analyzed by pausing the program, listing threads, switching, and inspecting backtraces. If the current thread is unclear, use info threads and thread thread_id. To improve performance, reduce thread count during initial debugging.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Deepin Linux
Research areas: Windows & Linux platforms, C/C++ backend development, embedded systems and Linux kernel, etc.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
