Here’s why debuggers are bad.
This article describes an alternative approach. There’s a tiny source library (just a single .c/.h pair) that implements some of these ideas, and an optional demo setup for it.
Study first, then type. The items below are best used to test beliefs, not create them.
-
Convenient checkpoints and value output. See the the
CP(),TV()andTS()macros from the source library, or make editor macros for things like this:printf ("%s:%i:%s: checkpoint\n", __FILE__, __LINE__, __func__);
If you don’t like having to tell
printf()what type you’re printing when the compiler already knows, check out the thePT()andTP()macros from the optionalformat_free_print.hheader in the source library download. -
A way to get a backtrace. The (GNU-specific)
backtrace()function and theaddr2lineprogram can do this. See thebacktrace_with_line_numbers()function orBT_ASSERT()macro from the source library. -
A way to look up the function and source location pointed to by a function pointer, so you can use instrumentation to find out what’s going to be called from a given point at run time. See
what_func()from the source library which does this using thenmprogram and dladdr() function. -
A strategy for dealing with memory errors. I use valgrind like this:
valgrind --leak-check=yes --undef-value-errors=no ./my_exe my_exe_arg 2>&1 | tee /tmp/valgrind_log
Valgrind looks sort of like a debugger, but you don’t have to operate inside it. There are other options, however.
-
A strategy for exploring your program’s call tree and sources statically. I use vim and cscope for C, and GNU global or exuberant ctags for other things. For whole-system exploration I like the HTML call graph and linked sources that global produces. The source library includes an example of how to integrate GNU cflow and global into your build system (in
Makefileandcflow_and_global.mkfiles). -
A decent build system, i.e. one that can rebuild your program fast. There are several things that may help with this:
-
The ccache program caches the results of compilation commands and reuses them when appropriate. It’s particularly helpful when your build system often rebuilds too much. It’s simple to use: just replacing
gccwithccache gccin your compilation recipes is usually enough. See theMakefilein the source library for an example. -
GNU binutils includes a new linker called
gold. It can do incremental linking, which is much faster for large projects. See theMakefilein the source library for details. -
The GNU automake and autoconf systems can add dependency tracking to your program automatically. They aren’t simple to use generally, but if you know you’re headed in that direction anyway it might be worth adopting them sooner rather than later.
-
This stuff can be extended arbitrarily. If you need to write some code to visualize your data you can do so in the most natural way using the language at hand, without any discontinuity between your basic instrumentation and those extensions.