An "error of intent" - also called a "logic error" - has occurred when your code compiles and runs without crashing but does not do what you intend. Typically you discover this because the output is incorrect. The methodology for debugging such errors is much the same as for run-time errors. The principal difference is that you do not have a line number from which to begin debugging. Instead, you should place print statements at strategic places in your code to track down the cause of the error, or trace your program's execution with DrJava.
One good preliminary step is to ensure that all of the code you expect to be executed actually gets executed. For example, consider the following code:
01 if( numPlayers == 8 && ! isDone ) 02 { 03 ... 04 }
Even though you believe that the body of this if
statement is
entered at runtime, you should place a breakpoint on its first statement
(line 03) or insert a print statement at the beginning of the then-clause
(i.e. between lines 02 and 03) and verify that the body is being
executed. If in fact it's not being executed, then setting a breakpoint at
the if statement and examining the values of numPlayers
and done
, or preceding
the if-test by
System.out.println( "numPlayers = " + numPlayers + " and done = " + done )
should help identify the problem.
We will next discuss two common kinds of logic error.
If your program runs but does not do anything (there is no output to the console
or it just sort of "stalls"), then there is a good chance that your program
is stuck somewhere in an infinite loop. This usually occurs
with while
loops,
but can happen with a for
loop as well.
One way to discover an infinite loop is to add a print statement at the beginning of each loop in your code. For example:
01 while (i >= 0) 02 { 03 System.out.println("In loop A."); 04 //... 05 }
You will know you are stuck in an infinite loop if your console output looks something like this:
In loop A. In loop A. In loop A. In loop A. In loop A. In loop A. In loop A. In loop A. In loop A. In loop A. In loop A. In loop A. In loop A. In loop A. In loop A. In loop A. In loop A. In loop A. In loop A. In loop A. In loop A. In loop A. In loop A. In loop A. In loop A. In loop A. In loop A. In loop A. In loop A. In loop A. In loop A. In loop A. In loop A. In loop A. In loop A. In loop A. In loop A. In loop A. In loop A. In loop A. In loop A. [...and so on, seemingly forever.]
To debug this problem, ensure that the while
test (or the termination
clause of a for loop) will eventually evaluate to false
somewhere
within the body of the loop because of a change to one of its constituent
variables. If it's not obvious why this isn't happening, step through the
body of the loop, watching the value of the variables contained in
the termination test.
Remember that Java does not evaluate an entire compound boolean expression if it doesn't have to because it can predict the final result without futher evaluation. This is called short-circuit evaluation. It is summarized in the following table.
Scenario | Java's Short-circuit Evaluation Rules |
//say A and B are boolean expressions if( A && B ) { //... } |
If A is true, then B is evaluated. If A is false, then B is not evaluated. |
//say A and B are boolean expressions if( A || B ) { //... } |
If A is true, then B is not evaluated. If A is false, then B is evaluated. |
This can become a problem only if the portion of the compound expression not being evaluated changes the value of a variable whose value you need later, typically by calling a method. For example, consider
if( x > 0 || readNextValue() ) { ... }
where readNextValue()
both reads the next input value required
by your program - a value you actually use later in the code - and returns
true or false, depending on whether it is successful doing so. But readNextValue()
will
not be called if x is positive. This kind of logic error is most easily discovered
either by tracing program execution, stepping into the if-test, or by adding
a print statement at the beginning of readNextValue()
.
Created by Terry Anderson (tanderso at uwaterloo dot ca) and adapted for CS 133 by JCBeatty. Last modified on 24 Sep 2006.