About
Relative Debugging
Traditional debuggers allow a user to control a
program and examine its state at any point of the execution. The
user sets breakpoints in the code, interactively examines program
variables, and verifies that these variables have expected values.
Erroneous values can be traced to erroneous code by using information
about program data flow. Relative debugging differs from traditional
debugging in two important respects. First, program variables
are compared not with user expectations, but with variables in
another reference program that is known to be correct. Second,
because the reference program is available to compute correct
values, the comparison process can be automated. Hence, the relative
debugging process proceeds as follows. The user first formulates
a set of assertions about key data structures in the reference
and the development versions. These assertions specify locations
at which data structures should be identical: violations of the
assertions indicate errors. The relative debugger is then responsible
for managing the execution of the two program versions, for validating
the supplied assertions by comparing the data structures, and
for reporting any differences. If differences are reported, the
user proceeds to isolate erroneous code by repeatedly refining
the assertions and reinvoking the relative debugger. Once the
erroneous region is small enough, traditional debugging techniques
can be used to correct the development version. Thus, the relative
debugger provides a quick and effective way of locating problems
in the development version.

A relative debugger provides
all the functionality of a traditional debugger, including commands
for program control, state access and breakpoints. However, the
heart of the relative debugger is a set of new commands, not available
in conventional debuggers. These commands support the relative
debugging methodology.
Because the reference and development versions of
the program are executed concurrently, a relative debugger must
be capable of handling two programs at the same time. It is useful
for the relative debugger to support the debugging of programs
written in different programming languages and executing on different
computers in a heterogeneous network. This makes it possible to
use the relative debugger when porting programs from one language
or computer to another.
A relative debugger checks user-supplied assertions
by comparing data structures in the reference and development
versions. It performs necessary transformations of different internal
data representations on different computers or in different languages.
When performing comparisons, the debugger must take into account
different data types, allowing for such issues as inexact equality
in floating point numbers, and differences in dynamic pointer
values. This aspect of the debugger will be illustrated in the
next section. Violations of assertions are reported to the user.
A number of approaches are possible for reporting differences
in data structures, ranging from text to advanced data visualization
techniques. If there are only a few differences, then the numeric
values of differences are printed out. If differences are numerous,
then visualization techniques are required to present them in
a meaningful way.