Programming tips to make debugging easier
- Don't try to use fancy tricks to shorten your code -
they make the code harder to read, debug, and maintain later.
- Split complicated expressions and calculations into a
series of smaller, simpler steps.
- When using 'if' statements put the action on a seperate
line from the condition test, e.g.
if (x < 3)
cout << "x is too small ";
Many debugging tools allow you to 'step' through a program
one line at a time in execution. Seperating the statement
into two lines makes it much clearer when the condition is
being checked vs when you are carrying out the associated
action.
- Add print (e.g. cout) statements that help during
the debugging process -- letting you know that you
reached certain points in the code, the values of key
variables at key points, ... whatever seems appropriate.
- Add a boolean constant for a debugging mode,
and embed print statements within your code that
only get used when in debug mode. E.g.
#include <iostream>
using namespace std;
const bool DebugMode = true;
int main(int argc, char *argv[])
{
if (DebugMode) {
// if the program is compiled/run in debug mode
// we'll print out all the command line arguments
cout << argc << " command line arguments supplied:\n";
for (int i = 0; i < argc; i++) {
cout << " " << i << ":" << argv[i] << endl;
}
}
return 0;
}
While debugging, set the constant to true so the
statements apply, then when 'finished' debugging
set the constant to false to turn them all off.
(This is much easier and safer than going through the code
to comment them all out.)
- If you #include <cassert> then you can include __LINE__
and/or __FILE__ in your debug print statements to display
which file and line number the message is coming from, e.g.
cout << "In " << __FILE__ << " on " << __LINE__;
cout << " variable X has value " << X << endl;
-
Debugging tips
Just a few ideas to try when you're stuck on a debugging problem...
- Identify how to consistently reproduce the problem - the first
step in figuring out what's going wrong!
- Focus on one problem at a time ... if this is during compilation
always tackle the top error message first (many others
may come from the compiler not being able to get past the first
bug correctly).
- Explain the problem to someone else - a friend, an enemy, the cat,
whatever. While describing the problem out loud you often think
about it more carefully/clearly, and the solution occurs to you.
- Get someone else to look over the code - often the problem is
immediately visible to someone else. (When you look at the code
your brain often takes shortcuts - seeing what it expects to see
rather than what is really there, making simple syntax and logic
errors ridiculously difficult to spot.)
- Take a break - go get a coffee, sleep on it, watch a bad movie,
or whatever. Often you need to clear your head and tackle the
problem with fresh eyes later.
- Try not to rush through segments of code - thinking carefully
about each line of code may be slightly slower, but can eliminate
lots of debugging nightmares.
- Learn to use a debugger - gdb is the beast of choice for us.
I've got some
short gdb notes here.
Common issues to look for
- If you're getting segmentation faults
look for null pointers or infinite recursion.
- If the compiler is complaining about undefined references
to a function, check that you haven't mistyped the function
name somewhere (check the prototype, the full function
implementation, and the calls - make sure they all match).
- If the compiler is complaining about variables not declared
in the current scope, check for typos (spelling the variable
name differently somewhere) and check to see if the variable
was declared inside a loop (in which case the scope of the
variable ends at the closing } for the loop).
- Look for uninitialized variables.
- Look for unchecked input values (don't blindly trust
user input!)
- Look for out-of range array accesses.
- Look for loops that go one time too many or one two few.
- Look for if/while conditions where you used = instead of ==.