Debugging Your Program
I feel that this is a topic that needs to be covered in detail. As it is, debugging is an incredibly important part of programming. If you run upon errors, you need to know how to find the issue, and resolve it. If you’re missing a semi-colon, you shouldn’t have to make a post to figure that out.
Please keep in mind that this isn’t specifically how you should debug. It isn’t a set of rules, it’s a set of recommendations. My recommendations may not necessarily be proper practice. If anything incorrect is found in this article please post so I can fix it. I don’t like to spread false knowledge.
Anyway, we’ll start basic, from acknowledging and understanding a compiler error, to single-stepping through a program with your IDE’s debugger.
Please note: I’m referencing C++ for Dummies 5th Edition by Stephen Randy Davis, pages 139-155.
Identifying An Error
Often times your program doesn’t work as planned, and won’t compile properly. Even the best programmers make mistakes, being able to identify what you did wrong is essential. There are two types of errors that exist; those that the C++ compiler can catch on its own, and those that the compiler can’t catch. Errors that C++ can catch are known as compiler-time errors. Compiler-time errors should be relatively easy to fix, because the compiler points you to where the problem is. All that garbage that’s spit out by the compiler has some use. Here’s an example. I forgot to put a semicolon after my return statement.
1 2 3 4
|
int main()
{
return 0
}
| |
Your compiler should generate an error something like…
\main.cpp(4) : error C2143: syntax error : missing ';' before '}'
Compiler errors differ from compiler to compiler, but its all going to generally be the same. In my case, I’m using Visual Studio 2008, but if you’re using Dev-C++, or G++, the same thing applies.
Now lets take this compiler error apart. The first part of it
\main.cpp(4)
says that the error is in the file main.cpp, on line 4. After that is
error C2143:
That’s the compiler specific error code. If you’re using Visual Studio, you can easily look up the error code on MSDN if you need to. After that the error states
syntax error :
Which tells you that you messed up some syntax. So you must not have typed something right. Then it tells me
missing ‘;’ before ‘}’
There’s a missing semi-colon before a closing bracket. Okay, so I know I’m missing a semi-colon, I know the error is on line 4, I know that its before the closing bracket. So I go to main.cpp, line 4, and before the closing bracket I need a semi-colon. Since the only thing that’s on line 4 is a closing bracket, I’ll just go up to line three and OH! I notice I forgot to put a semi-colon after
return 0
. Aknowledging a compiler error should be as easy as that.
The other type of error that C++ doesn’t catch, is called a run-time error. Run-time errors are often much more tricky to catch.
Debugging Techniques
There’s several ways that one can debug a program. The two that I use most often are the WRITE technique, and single-step debugging. Firstly, I’ll cover the WRITE technique. It invovles creating output statements for all of your variables, so you can see the value of everything. I’ll use this program example from C++ for Dummies 5th edition.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
|
// ErrorProgram – This program averages a series
// of numbers, except that it contains
// a fatal bug.
#include <cstdio>
#include <cstdlib>
#include <iostream>
using namespace std;
int main(int nNumberofArgs, char *pszArgs[])
{
cout << "This program is designed to crash!"
<< endl;
int nSum;
int nNums;
// accumulate input numbers until the
// user enteres a negative number, then
// return the average
nNums = 0;
while(true)
{
// enter another number to add
int nValue;
cout << "Enter another number:";
cin >> nValue;
cout << endl;
// if the input number is negative...
if(nValue < 0)
{
// ... then output the average
cout << "Average is: "
<< nSum/nNums
<< endl;
break;
}
// not negative, add the value to
// the accumulator
nSum += nValue;
}
cin.ignore(10000, '\n');
return 0;
}
| |
When executing this code, you’ll get a run-time error. An easy way to solve what’s being messed up is using the WRITE technique. Every time you go into the while loop, have it output the value of nNums.
1 2 3 4 5 6 7
|
While(true)
{
// output
cout << “nNums = “ << nNums << endl;
// The rest of the program is unchanged
}
| |
Output will look like
This program is designed to crash!
nNums = 0
Enter another number:1
nNums = 0
Enter another number:2
nNums = 0
Enter another number:3
nNums = 0
Enter another number: |
You can see that nNums is being initialized to 0, but where is it being incremented? It’s not, and this is the bug. Clearly nNums should have been incremented during each loop of the input section. By using the WRITE technique, we told out program to output the value of nNums every loop, thereby finding out that it wasn’t being properly incremented.
For smaller program, the WRITE technique works reasonably well, but as things get larger, it’s harder to output all your variables, and it just starts to seem like a waste of time. Instead, we’ll rely on the debugger. First, lets define a debugger. A debugger is a tool built into most development environments (and although they differ, most debuggers work on the same principles.) A programmer controls the debugger through commands by the means of the same interface as the editor. You can access these commands in menu items or by using hotkeys. The debugger allows the programmer to control the execution of his/her program. He/she can execute one step at a time in the program, he/she can stop the program at any point, and he/she can examine the value of variables. To appreciate the power of the debugger, you need to see it in action. Using this is hard to explain in words (and I’m terrible at putting things into words.) So for further information on debugging, I’ll link you to a very handy web page.
http://www.cprogramming.com/tutorial/debugging_concepts.html
If there’s anything that needs to be added, let me know.
While I was proof reading, I’m noticing I’m doing a terrible job at explaining this. The post is open for improvements.
-Thumper