Debugging
Debugging is an essential skill for any C programmer, involving the process of identifying and resolving issues in code that cause unexpected behavior or crashes. This section covers two key approaches: using gdb for interactive debugging and practical techniques to systematically isolate problems.
Using gdb
gdb (GNU Debugger) is a powerful command-line tool for inspecting and controlling program execution. Here’s how to use it:
- Compile with debugging symbols:
<code class="language-bash"> gcc -g my<em>program.c -o my</em>program</code>
- Start
gdb:
<code class="language-bash"> gdb my_program</code>
- Common commands:
– Run: run (or r) to execute the program
– Breakpoints: break [function] to pause at a specific function
– Step through code: step (execute next line) or next (skip function calls)
– Inspect variables: print [variable] to view variable values
– View call stack: backtrace to see the execution flow
Example workflow:
- Compile factorial program with debug symbols
- Start
gdband set breakpoint atfactorial() - Run program → pause at breakpoint
- Step through code to observe variable changes
- Use
print nto check values during execution
Pro Tip: Use info locals to see all local variables in the current function—critical for complex debugging scenarios.
| Command | Purpose |
|---|---|
run |
Execute program |
break [function] |
Set breakpoint |
step |
Step into next line |
next |
Step to next line (skip function calls) |
print [variable] |
View variable value |
backtrace |
Show call stack |
Practical Debugging Techniques
- Reproduce the bug
Always create a minimal test case that consistently reproduces the issue. Example: If a program crashes with large input files, test with progressively smaller files.
- Use print statements
Add targeted printf statements to track variable values and execution flow.
Example factorial output:
<code> Entering factorial(5)</p> <p> Entering factorial(4)</p> <p> Entering factorial(3)</p> <p> Entering factorial(2)</p> <p> Entering factorial(1)</p> <p> Returning 1</p> <p> Returning 2</p> <p> Returning 6</p> <p> Returning 24</p> <p> Returning 120</code>
- Check memory leaks
Use valgrind to detect memory issues:
<code class="language-bash"> valgrind --leak-check=full --show-leak-kinds=definite your_program</code>
- Use conditional breakpoints
Pause execution only when specific conditions are met:
<code class="language-gdb"> break if n < 0</code>
- Isolate problems
Test functions in isolation. Example: Create a dedicated test_factorial() function to verify logic without dependencies.
Summary
This section covered using gdb for interactive debugging and practical techniques to efficiently identify and resolve issues in C code. Remember: debugging is a skill that improves with practice.
💡 Always start with a minimal reproducible test case. This saves hours of debugging time and helps isolate root causes faster.