CS230 Data Structures, Wellesley College, Spring 2007

Lab 2

Debugging, Debugging, and More Debugging...

As described on the appendix on Debugging in Allen Downey's How to Think Like a Computer Scientist: Java Version ," there are three types of errors that arise in programs:

In this lab, you will have the opportunity to track down and fix many examples of compile-time, run-time and semantic errors. The goal of your work is not simply to produce a working program at the end, but also to experience many of the error messages that can arise when compiling and running Java programs, to learn the association between the cause of an error and subsequent program behavior, and to practice important debugging skills such as the use of println statements.

As always when you are starting a working cs230 session, update your local copy of the cs230 file system, by running the following commands in a Linux shell:

> cd ~/cs230
> cvs update -d

Check your cs230 directory, to make sure you can see the lab2/ManyBugs.java file, which will be working with today. You may want to get a hard copy of your program (ManyBugs.java) at this point, to examine during the debugging process, and keep notes on it.

Part a: Fixing Compile-time Errors

Your first goal is to fix all of the errors that are generated during the compilation stage, but you must fix these errors one at a time! You should cycle through the three steps of:

until you have a version of the program that compiles successfully.

Remember that often the real cause is located elsewhere in the code, and the error messages are not always informative. Add a comment on your hardcopy describing the cause of the error. Finally, modify the code to fix this error and recompile the file. Continue this process until the entire file compiles successfully. If you cannot figure out how to fix a particular error, temporarily comment out the code that appears to be the cause, and move on to the next error in the code file.

When your code compiles successfully, you may want to make a hardcopy (paper) of this version of the code. You can use this hardcopy to record run-time errors that arise when you now try to execute the program.

Part b: Fixing Run-time Errors

Run-time errors are those that occur during execution of the program. Examine the main method to see the order of execution of program statements and then try running the program. When an error occurs, an error message will be printed on your terminal window. Examine the first error that occurred. If the error generated an Exception, examine the method in which the error occurred and try to determine the cause. If the cause is not immediately apparent, place println statements inside the method to help observe its behavior in more detail. The following method definition illustrates the use of println statements to monitorits execution:

public static int countEvenNumbers (int numArray[]) {
    System.out.println("Entering countEvenNumbers");
    numEvens = 0;
    System.out.println("numEvens = " + numEvens);
    for (int i = 0; i < numArray.length; i++) {
      System.out.println("i = " + i + " numArray[i] = " + numArray[i]);
      if (numArray[i] % 2 == 0)
          numEvens++;
      System.out.println("numEvens = " + numEvens);
    }
    return numEvens;
}

After you have determined the cause of the error, circle the location of the error on your hardcopy of the version of the code that compiles successfully, and write a comment describing the nature of the error. If an Exception was generated, include the name of the Exception in your comment. Continue this process until the entire code file runs successfully. If you had placed println statements in the code, you may want to comment them out after you have fixed an error, in order to reduce the printout produced by the program.

When your code runs successfully, you may want to make hardcopy (paper) of this version of the code. You can use this hardcopy to record semantic errors that still exist in the program.

Part c: Fixing Semantic Errors

Now that your program is running, carefully examine all of the output that is produced. Examine the comments in the code file that describe the intended behavior of the program. When you find a discrepancy between the result you expect and the actual results produced by the program, try to determine the cause of the discrepancy. Also examine the particular test cases that appear in the main method, and consider whether they test each of the other methods adequately. It is possible that a method works correctly for the particular test case that was chosen, but does not work for all inputs. Examine the method definitions carefully and think about whether there are some inputs for which the method would not work correctly. When you find an error, circle the location of the error on your hardcopy of the version of the program that runs successfully. Add a comment describing the cause of the error. Fix the error and again run the program to see if it now produces the expected results. If the cause of the problem is not immediately apparent, again consider adding println statements to monitor the behavior of the code more closely. Semantic errors can be subtle and are often the most difficult to track down and fix. There are several semantic errors in this program!