🔥 This article is worth: saving you 80% of your debugging time, from beginner to expert, all in one article for Linux program debugging!
Debugging is a core skill that every programmer must master when developing programs in a Linux environment. However, many students only know how to use <span>printf</span> and are at a loss when encountering problems. This article will take you from zero to systematically mastering the complete technical stack of Linux program debugging.
📊 Debugging Method Selection Guide
| Debugging Stage | Recommended Tool Combination | Learning Cost | Effectiveness Index |
| Compilation Errors | gcc + Static Analysis | ⭐ | 🔥🔥🔥🔥🔥 |
| Runtime Errors | gdb + Logs | ⭐⭐ | 🔥🔥🔥🔥 |
| Memory Issues | valgrind + asan | ⭐⭐⭐ | 🔥🔥🔥🔥🔥 |
| Performance Optimization | perf + Flame Graph | ⭐⭐⭐⭐ | 🔥🔥🔥🔥 |
| Production Failures | eBPF + Dynamic Tracing | ⭐⭐⭐⭐⭐ | 🔥🔥🔥🔥🔥 |
🎯 Stage One: Compile-Time Debugging (Nip Errors in the Bud)
1.1 Enable Compiler’s Watchful Eye
# Ultimate Compilation Options (Recommended to Bookmark)
gcc -Wall -Wextra -Wpedantic -Wshadow -Wpointer-arith \
-Wcast-align -Wwrite-strings -Wmissing-prototypes \
-Wmissing-declarations -Wredundant-decls -Wnested-externs \
-Winline -Wuninitialized -Wconversion -Wstrict-prototypes \
-g -O0 -o myapp main.c
# C++ Specific Options
g++ -std=c++17 -Wall -Wextra -Wpedantic -Weffc++ \
-Wold-style-cast -Woverloaded-virtual -Wsign-promo \
-Wnon-virtual-dtor -g -O0 -o myapp main.cpp
1.2 Practical Use of Static Analysis Tools
# Install clang static analyzer
sudo apt install clang-tools
# Scan for code defects (generate HTML report)
scan-build -o static-analysis-report gcc -o myapp main.c
# View report
firefox static-analysis-report/index.html
1.3 Practical Case: Finding Hidden Bugs
// Problematic Code
typedefstruct {
char name[32];
int age;
} Person;
voidprint_person(Person *p) {
printf("Name: %s, Age: %d\n", p->name, p.age); // Compiler Warning: p.age should be p->age
}
// Corrected Code
voidprint_person(const Person *p) {
if (p) {
printf("Name: %s, Age: %d\n", p->name, p->age);
}
}
🐛 Stage Two: Runtime Debugging (GDB Practical Secrets)
2.1 Quick Start with GDB
# Compile with Debug Information
gcc -g -O0 -o myapp main.c
# Start GDB Debugging
gdb ./myapp
# Common Command Quick Reference
(gdb) break main # Set breakpoint at main function
(gdb) run arg1 arg2 # Run program with arguments
(gdb) next # Step over
(gdb) step # Step into
(gdb) continue # Continue execution
(gdb) print var # Print variable value
(gdb) backtrace # View call stack
(gdb) quit # Exit GDB
2.2 Advanced Debugging Techniques
# Conditional Breakpoints (trigger only under specific conditions)
(gdb) break myfunc.c:42 if count > 100
# Watchpoints (monitor variable changes)
(gdb) watch *0x7fffffffe000
(gdb) rwatch my_var # Trigger on read
(gdb) awatch my_var # Trigger on read/write
# Backtrace Debugging (Time Travel Debugging)
gcc -g -O0 -finstrument-functions -o myapp main.c
# Debugging core file (analyzing crashes)
gdb ./myapp core.12345
(gdb) bt full # View full call stack
2.3 GDB TUI Mode (Visual Debugging)
# Start TUI Interface
gdb -tui ./myapp
# Shortcut Operations
Ctrl+X A # Switch to TUI mode
Ctrl+X 1 # Single window mode
Ctrl+X 2 # Dual window mode (source code + assembly)
Ctrl+X o # Switch window focus
🔍 Stage Three: Memory Debugging (Say Goodbye to Memory Leaks)
3.1 Comprehensive Detection with Valgrind
# Install Valgrind
sudo apt install valgrind
# Memory Leak Detection (most comprehensive options)
valgrind --leak-check=full \
--show-leak-kinds=all \
--track-origins=yes \
--verbose \
--log-file=valgrind.log \
./myapp
# Performance Analysis (generate call graph)
valgrind --tool=callgrind ./myapp
kcachegrind callgrind.out.12345 # Visual analysis
3.2 Address Sanitizer (Quick Memory Detection)
# Enable ASan at compile time (recommended)
gcc -fsanitize=address -g -O1 -fno-omit-frame-pointer -o myapp main.c
# Run program (automatically detect memory errors)
./myapp
# Example Output:
==12345==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x6020000000f4
3.3 Memory Debugging Practical Cases
// Memory Leak Example
voidmemory_leak_demo() {
char *buffer = malloc(1024);
// Forget to free, causing memory leak
}
// Dangling Pointer Example
voiddangling_pointer_demo() {
char *buffer = malloc(100);
free(buffer);
buffer[0] = 'x'; // Use freed memory
}
// Correct Memory Management
voidgood_memory_management() {
char *buffer = malloc(100);
if (buffer) {
// Use buffer...
free(buffer);
buffer = NULL; // Prevent dangling pointer
}
}
📈 Stage Four: Performance Analysis (Identify Performance Bottlenecks)
4.1 Perf Performance Analysis Tool
# Install Perf
sudo apt install linux-tools-generic
# Basic Performance Statistics
perf stat ./myapp
# Record Call Stack (generate flame graph)
perf record -g ./myapp
perf report # Interactive view
# Real-time Monitoring
perf top -p $(pgrep myapp)
4.2 Flame Graph Visualization
# Install Flame Graph Tool
git clone https://github.com/brendangregg/FlameGraph.git
# Generate Flame Graph
perf record -g -F 99 -a -- sleep 30
perf script | FlameGraph/stackcollapse-perf.pl | \
FlameGraph/flamegraph.pl > perf.svg
# View Flame Graph in Browser
firefox perf.svg
4.3 Performance Optimization Practical Cases
// Performance Problem Code
voidslow_function() {
for (int i = 0; i < 1000000; i++) {
printf("%d\n", i); // Frequent system calls
}
}
// Optimized Code
voidfast_function() {
char buffer[8192];
int offset = 0;
for (int i = 0; i < 1000000; i++) {
offset += snprintf(buffer + offset, sizeof(buffer) - offset,
"%d\n", i);
if (offset > 7000) { // Batch output
printf("%s", buffer);
offset = 0;
}
}
if (offset > 0) {
printf("%s", buffer);
}
}
🔄 Stage Five: Multithreaded Debugging (The Savior of Concurrent Programming)
5.1 Helgrind for Detecting Race Conditions
# Install Helgrind (part of Valgrind)
sudo apt install valgrind
# Detect Thread Errors
valgrind --tool=helgrind ./myapp
# Example Output:
==12345== Possible data race during write of size 4 at 0x601040 by thread #1
5.2 GDB Multithreaded Debugging
# View All Threads
(gdb) info threads
# Switch Threads
(gdb) thread 2
# Set Thread Breakpoint
(gdb) break worker.c:42 thread 3
# Lock Scheduler (debug only current thread)
(gdb) set scheduler-locking on
# Execute Command on All Threads Simultaneously
(gdb) thread apply all bt
5.3 Thread Debugging Practical Cases
#include <pthread.h>
#include <stdio.h>
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
int counter = 0;
void* thread_func(void* arg) {
for (int i = 0; i < 1000; i++) {
pthread_mutex_lock(&mutex);
counter++; // Protect shared resource
pthread_mutex_unlock(&mutex);
}
return NULL;
}
🚀 Stage Six: Production Environment Debugging (Non-Disruptive Service)
6.1 eBPF Modern Debugging Techniques
# Install BCC Toolset
sudo apt install bpfcc-tools
# Real-time System Call Tracing
sudo execsnoop-bpfcc
# Trace File Operations of Specific Process
sudo opensnoop-bpfcc -p $(pgrep myapp)
# Network Connection Tracing
sudo tcpconnect-bpfcc
# Function Call Tracing
sudo funccount-bpfcc 'vfs_*'
6.2 Dynamic Tracing Tool Combinations
# strace to trace system calls
strace -f -e trace=network,signal -p $(pgrep myapp)
# ltrace to trace library function calls
ltrace -f -p $(pgrep myapp)
# Use bpftrace (more advanced eBPF tool)
sudo bpftrace -e 'tracepoint:syscalls:sys_enter_openat { printf("%s opened %s\n", comm, str(args->filename)); }'
🛠️ Stage Seven: Modern Debugging Environment
7.1 VS Code Debug Configuration
Create <span>.vscode/launch.json</span>:
{
"version":"0.2.0",
"configurations":[
{
"name":"Linux Debug",
"type":"cppdbg",
"request":"launch",
"program":"${workspaceFolder}/build/myapp",
"args":["--config","debug.conf"],
"stopAtEntry":false,
"cwd":"${workspaceFolder}",
"environment":[
{"name":"LD_LIBRARY_PATH","value":"${workspaceFolder}/lib"}
],
"externalConsole":false,
"MIMode":"gdb",
"setupCommands":[
{
"description":"Enable pretty-printing",
"text":"-enable-pretty-printing",
"ignoreFailures":true
}
],
"preLaunchTask":"build"
}
]
}
7.2 CMake Debug Build
# CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
project(MyApp)
# Debug Build Configuration
set(CMAKE_BUILD_TYPE Debug)
set(CMAKE_CXX_FLAGS_DEBUG "-g -O0 -fsanitize=address -fno-omit-frame-pointer")
set(CMAKE_C_FLAGS_DEBUG "-g -O0 -fsanitize=address -fno-omit-frame-pointer")
# Build Steps
mkdir build && cd build
cmake -DCMAKE_BUILD_TYPE=Debug ..
make -j$(nproc)
📋 Summary of Best Debugging Practices
Debugging Strategy Pyramid
🎯 Production Environment Monitoring (eBPF)
↑
⚡ Performance Optimization (perf + Flame Graph)
↑
🔍 Memory Debugging (valgrind + asan)
↑
🐛 Logic Debugging (gdb + logs)
↑
✅ Compile-Time Checks (Static Analysis)
Debugging Checklist
- • Compile-Time: Enable all warnings + Static Analysis
- • Memory: Dual check with Valgrind + Address Sanitizer
- • Performance: Establish performance baseline + Regular performance testing
- • Concurrency: Multithreaded stress testing + Helgrind checks
- • Production: Deploy monitoring + eBPF dynamic tracing
Quick Reference Card for Debugging Tools
# Quick Debugging Command Set
alias debug-gcc='gcc -Wall -Wextra -g -O0 -o'
alias debug-gdb='gdb -tui'
alias debug-valgrind='valgrind --leak-check=full --show-leak-kinds=all'
alias debug-perf='perf record -g'
alias debug-strace='strace -f -e trace=all'
🎓 Learning Roadmap
Beginner Stage (1-2 weeks)
- 1. Master gcc warning options
- 2. Learn basic debugging with gdb
- 3. Understand valgrind memory detection
Intermediate Stage (2-4 weeks)
- 1. Master advanced gdb techniques
- 2. Learn to use perf for performance analysis
- 3. Master multithreaded debugging
Expert Stage (1-3 months)
- 1. Proficient use of eBPF dynamic tracing
- 2. Build automated debugging processes
- 3. Establish production environment monitoring systems
🏆 Conclusion: Debugging is a Programmer’s Superpower
By mastering these debugging techniques, you will gain:
- • 80% of bugs can be detected during the development phase
- • 50% of performance improvement potential can be uncovered
- • 90% of production failures can be quickly located
Remember: Debugging is not just about fixing bugs, but about better understanding the program. Every debugging session is a deep exploration of the system.
“Debugging is not about fixing bugs, it’s about understanding systems.” — A famous quote from a debugging master
📱 Scan to follow ‘Programmer Intelligence Bureau’ for more practical tips!
💬 Let me know in the comments: What is your favorite debugging tool?