Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
C++ For Dummies (2004) [eng]-1.pdf
Скачиваний:
67
Добавлен:
16.08.2013
Размер:
8.09 Mб
Скачать

140 Part II: Becoming a Functional C++ Programmer

program as these different output statements are executed. A second approach is to use a separate program called a debugger. A debugger enables you to con­ trol your program as it executes.

I cover both of these debugging techniques in this chapter.

Choosing the WRITE Technique for the Problem

Adding output statements to the C++ source code to find out what’s going on within the program is known as using the WRITE statement approach. It gained this name back in the days of early programs when programs were written mostly in COBOL and FORTRAN. Fortran’s output is through the WRITE command.

The following “buggy” program shows how the WRITE approach works.

The following program is supposed to read a series of numbers from the key­ board and return their average. Unfortunately, the program contains two errors, one that makes the program crash and one that causes the program to generate incorrect results.

The following steps route out the problem. First, enter the program as writ­ ten (or copy the program ErrorProgram1.cpp from the CD-ROM).

// ErrorProgram - this program averages a series

//

of numbers, except that it contains

//

at least one 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 enters a negative number, then // return the average

nNums = 0; while(true)

{

// enter another number to add

Chapter 10: Debugging C++ 141

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;

}

//wait until user is ready before terminating program

//to allow the user to see the program results system(“PAUSE”);

return 0;

}

Build and execute the program as normal. I enter my trusty 1, 2, and 3 followed by –1, but get quite a shock when the nasty message shown in Figure 10-1 appears instead of the expected average.

Figure 10-1 appeared using Dev-C++ 4.9.8.0. User results may differ with differ­ ent C++ compilers, but the general idea that you did something really bad should stay the same.

Figure 10-1:

The initial version of Error Program terminates suddenly instead of generating the expected output.

142 Part II: Becoming a Functional C++ Programmer

Catching bug #1

Though unexpected, the error message shown in Figure 10-1 contains some useful information. However, don’t let the Cancel button get your hopes up. Despite the message, clicking on Cancel doesn’t bring you any closer to find­ ing the problem than does the OK button. Windows simply says that it can’t really help you find the problem.

Fortunately, the first line of the error message is descriptive of the problem. “Application error” means that someone tapped Windows on the back with an important message that Windows wasn’t expecting and didn’t know what to do with. The message is “Integer division by zero.” Apparently, someone divided a number by zero (pretty astute, huh?). The message also spits out the memory address where the division occurred, but this is of little use because you have no idea where in the program that address may be.

The divide by zero error message isn’t always so straightforward. For exam­ ple, suppose that the program lost its way and began executing instructions that aren’t part of the program? (That happens a lot more often than you might think.) The CPU may just happen to execute a divide instruction with a denominator of zero, thereby generating a divide by zero error message and masking the source of the problem. (An errant program is like a train that’s jumped the track — the program doesn’t stop executing until it hits some­ thing really big.)

A review of the program reveals only one obvious division:

cout << “Average is: “

<<nSum/nNums

<<endl;

Just because division appears only once, it doesn’t meant that this is the only place where division occurs. The compiler may have generated a division on its own as a result of some other C++ instruction that you wrote. In addition, the Standard C++ Library is just full of divisions.

I feel reasonably certain that at the time of the division, nNums must have been equal to zero. nNums is supposed to be a count of the number of values entered. You can add a cout statement to track the value of nNums within the while loop as follows:

while(true)

{

// output

cout << “nNums = “ << nNums << endl;

// ...the rest of program unchanged...

Chapter 10: Debugging C++ 143

This addition generates the following output:

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 where nNums is initialized to 0, but where is it incremented? It isn’t, and this is the bug. Clearly nNums should have been incremented during each loop of the input section. I edit the while loop into a for loop as follows:

for (int nNums = 0; ;nNums++)

Catching bug #2

Having fixed a bug, execute the program using the same 1, 2, 3, and –1 input that crashed the program earlier. This time, the program doesn’t crash, but it doesn’t work either. The output shown here includes a ridiculous value for average:

This program generates incorrect results

Enter another number:1

Enter another number:2

Enter another number:3

Enter another number:-1

Average is: 1456814

Press any key to continue...

Apparently, either nSum or nNums (or both) isn’t being calculated properly. To get any farther, you need to know the value of these variables. In fact, it would help to know the value of nValue as well because nValue is used to calculate nSum.

Now you modify the for loop as follows to learn the values of the nSum, nNums, and nValue (this version of the program appears on the CD-ROM as ErrorProgram2.cpp):

144 Part II: Becoming a Functional C++ Programmer

// ErrorProgram - this program averages a series

//

of numbers, except that it contains

//

at least one fatal bug

#include <cstdio>

#include <cstdlib>

#include <iostream>

using namespace std;

int main(int nNumberofArgs, char* pszArgs[])

{

cout << “This program generates incorrect results”

 

 

<< endl;

 

// accumulate input numbers until the

 

// user enters a negative number, then

 

// return the average

 

int nSum;

for (int nNums = 0; ;nNums++)

{

//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 << “\nAverage is: “

<<nSum/nNums

<<“\n”;

break;

}

// output critical information

cout << “nSum = “ << nSum << “\n”; cout << “nNums= “ << nNums << “\n”; cout << “nValue= “<< nValue << “\n”; cout << endl;

//not negative, add the value to

//the accumulator

nSum += nValue;

}

//wait until user is ready before terminating program

//to allow the user to see the program results system(“PAUSE”);

return 0;

}

Chapter 10: Debugging C++ 145

Notice the addition of the output statements to display nSum, nNums, and nValue on each iteration through the loop.

The result of executing the program with the now standard 1, 2, 3, and –1 input is shown next. Even on the first loop, the value of nSum is unreasonable. In fact, at this point during the first loop, the program has yet to add a new value to nSum. You would think that the value of nSum should be 0.

This program generates incorrect results

Enter another number:1

nSum = 4370436 nNums= 0 nValue= 1

Enter another number:2

nSum = 4370437 nNums= 1 nValue= 2

Enter another number:3

nSum = 4370439 nNums= 2 nValue= 3

Enter another number:-1

Average is: 1456814

Press any key to continue . . .

On careful examination of the program, nSum is declared, but it isn’t initial­ ized to anything. The solution is to change the declaration of nSum to the following:

int nSum = 0;

Note: Until a variable has been initialized, the value of that variable is indeterminate.

When you have convinced yourself that you have found the problem, “clean up” the program as follows (this version is ErrorProgram3.cpp on the enclosed CD-ROM):

// ErrorProgram - this program averages a series // of numbers

#include <cstdio> #include <cstdlib> #include <iostream>