How to Debug Chez Scheme Programs
R. Kent Dybvig
August 2002
When a program fails to operate as it should, it is said to have a bug. A bug is the root cause of an observed behavior, such as failure to terminate, failure to perform some action, termination with an error message, or merely producing incorrect results.
The process of debugging a program is one of finding all of the bugs and "exterminating" them. This process first requires feeding the program a representative set of test cases, observing the results, and determining for which of the test cases the program fails. If the program fails for any of the test cases, the next step is to find the cause of the failure, i.e., the bug. Once a bug has been found, it must be fixed and the debugging process started again from scratch. It is important to retest all of the test cases, even those that originally succeeded, after every change to the program.
Designing good test cases involves the notion of "complete coverage." Each part of the program must be tested with sets of values that are representative of those it might receive in actual use. For small programs, this is usually straightforward. For large or complex programs, obtaining complete coverage is difficult and often labor-intensive.
Finding a bug once failure has been noted, while often easy, is sometimes quite challenging. The most important thing to remember is that the basic law of cause and effect is always at work. That is, the incorrect behavior exhibited by a program is the result of a bug in that program. (In some cases, it may also be the result of a bug in the operating system.) An important key to successful debugging is to develop an understanding of the cause of the erroneous behavior. Only then can an appropriate fix be made.
Once a bug has been found, it is often a simple matter to fix the bug, although a bug that results from a serious logic error on the part of the programmer may precipitate a complete rewrite of the program.
It is sometimes tempting to hack at at a piece of code repeatedly without truly understanding why it's not doing what it should do until something approximating correct behavior materializes. More often, this simply wastes a lot of time. Even if hacking at the code appears to work, the result will likely just be more subtly incorrect, and ugly.
This document focuses on techniques for finding bugs. It is aimed primarily at beginning programmers who are using Chez Scheme or Petite Chez Scheme to write fairly simple programs, but most of the techniques described here are also useful for more complex programs and for other Scheme systems or even other programming languages. The document is organized into two sections:
... continue reading