"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." - Brain W. Kernighan
Debugging is the process of finding and resolving bugs. Debugging tactics can involve interactive debugging, control flow analysis, unit testing, integration testing, log file analysis, monitoring at the application or system level, memory dumps, and profiling. Many programming languages and software development tools also offer programs to aid in debugging, known as debuggers.
- Print/Trace debugging - watching the flow of execution after adding print statements to the original code (bad but quick)
- Remote debugging - connect to a remote system with a debugger, monitor the execution and state
- Post Mortem debugging - analysis of a memory dump from a program that has crashed
- Profiling - not debugging per se, but a useful technique for analysing a running program to look for issues.
- Bohrbug - bug that manifests itself consistently under a set of conditions
- Heisenbug - bug that alters its' characteristics when studied
- Construct a Hypothesis
- Construct an Experiment
- Hypothesis proved? Go to step 1.
- Need more evidence? Got to step 2.
The GNU Debugger (GDB) is a portable debugger that runs on many Unix-like systems and works for many programming languages, including Ada, C, C++, Objective-C, Free Pascal, Fortran, Go, and partially others.
In order to compile code into an executable readable by gdb
it needs to be compiled without optimization (-O0
) and in debug mode (-c=dbg
).
For additional debugging information, available only to gdb, use flag -ggdb
.
--copt=-O0
--copt=-ggdb
-c=dbg
Example: bazel build --copt=-O0 --copt=-ggdb -c=dbg //...
rr aspires to be your primary C/C++ debugging tool for Linux, replacing — well, enhancing — gdb. You record a failure once, then debug the recording, deterministically, as many times as you want. The same execution is replayed every time.
Usage: rr usage examples
If you encounter the error:
rr needs /proc/sys/kernel/perf_event_paranoid <= 1, but it is 3.
Change it to 1, or use 'rr record -n' (slow).
Consider putting 'kernel.perf_event_paranoid = 1' in /etc/sysctl.conf
Try:
sudo sh -c 'echo 1 >/proc/sys/kernel/perf_event_paranoid'
Then:
rr record PROGRAM.o && rr replay
rr allows for a very easy catch of places where core dumps occur. This can be done once the within the replay session by using the catch signal throw
command and reversing to the previous statement:
catch signal SIGINT
run
And after the core dump occurring:
reverse-next
gdb
<executable built with no optimization and in debug mode>- If you're debugging an executable throwing (ex. core dumping) you can use:
catch signal all
- Moving around:
b
source.cpp - set breakpoint,r
- run,n
- next,c
- continue,p
variable - observe tui enable
/tui disable
- GUI
For isolating compiler errors more easily:
bazel build //... 2>&1 | grep -ie error\: -C3