@device[postscript]
@make[report]
@chapter[The @i(dbx) Source Code Debugger]

The @i(dbx) source code debugger is one of the most powerful tools
available to programmers
because it helps you locate @b[runtime] errors in your source code.
Runtime errors,
in contrast to @b(compiletime) errors,
are errors in a program's logic,
not errors in its syntax.
Runtime errors only show up when you execute a program.


Runtime errors come in several flavors:
@begin(itemize)
Your program runs all right but gives you undesired results.

Your program does nothing.
It may be waiting for you to enter data,
or it may be stuck in an infinite loop.
If it is infinite looping,
the only way you can stop the program
is by typing Ctrl-C.

Your program displays output at a furious and unending rate.
This usually indicates an infinite loop and
the only way you can get it to stop is by typing Ctrl-C.

@begin[multiple]
Your program produces a fatal error and generates a @b[fatal error]
error message.
This happens when a program violates the operating system's rules
by trying something like dividing by zero or accessing
memory that doesn't belong to it.
When a program errs in this manner,
Unix takes a snapshot of its representation in memory and deposits
the image in a file named @b[core] in the current directory.

(Note that Unix at Project Athena has been set up so
that @i[core] files @b[are not] generated automatically.
This is because @i[core] files usually consume a lot of disk space,
and non-programmers don't need the headache of having @i[core] files
push them over their file system quota.)
@end[multiple]
@end(itemize)
@i(dbx) is great for isolating these kinds of problems.
Even if you know just a little bit about the debugger,
it will take a lot of the pain out of the debugging process.

@b[NOTE:] as nice as @i(dbx) is, the debugger is not perfect.
Unfortunately,
the debugger has several runtime bugs of its own.
See the following @i[dbx] tutorial for more information.
Also see @ux[Appendix G] for an introduction to the @i[Saber-C]
programmming environment.
@i[Saber-C] provides a more stable debugging environment.

@section[Using @i(dbx)]

Before you can use @i(dbx) on a program,
you @b[must] recompile the program using @i(cc's) @p(-g) option:
@begin(example)
athena% @b[cc   -g   source.c]
@end(example)
Under this option,
@i(cc) creates additional information about the program and deposits
it in a @b(symbol table).
The debugger must have this symbol table to do its work.

You start @i(dbx) by typing:
@begin(example)
athena% @b[dbx]   @p(executefile)
@end(example)
where @i(executefile) is the executable version of the program.
(If you have used @i(cc) without the @i(-o) option,
@i(executefile) is @i(a.out)).
As it starts up,
@i(dbx) displays a message similar to the following:
@begin(example)
dbx version 3.11 of 10/2/85 18:33 (mit-paris)
type 'help' for help.
reading symbolic information ...
@end(example)
before displaying the @i(dbx) command prompt:
@begin(example)
(dbx)
@end(example)

@section[A Note About @i(core) Files]

As mentioned earlier,
Project Athena has disabled automatic core dumps.
If you need to use a core file to debug a program,
you can enable core dumps with the @i[limit] command].
Use the @i[quota] command as follows to determine how much
disk space you have free:
@begin[example]
athena% @b[quota  -v]
@end[example]

Now use the @i[limit] command to set core files to a reasonable
size so that you won't exceed your quota when the file gets generated.
For instance,
suppose you want to limit the size of your core files to 100 blocks.
Use @i[limit] like this:
@begin[example]
athena% @b[limit   coredumpsize   100]
@end[example]

If your current directory has a @i(core) file in it,
@i(dbx) will attempt to use it even if the file has nothing to do with
the program you are tying to debug.
If @i(dbx) finds a @i(core) file,
it displays this message before issuing its command prompt:
@begin(example)
[using memory image in core]
@end(example)

When you have finished using a @i[core] file,
make sure you remove it.

@section[The @i(dbx) Debugging Process]

@i(dbx) helps you debug a program by letting you control the
program's execution.
The debugger lets you set @b(breakpoints),
places in the program where execution is suspended.
With execution suspended,
you can use @i(dbx) to examine the values of the program's variables
and expressions.
The following is an outline of a simple debugging session:
@begin(enumerate)
You start @i(dbx).

You set breakpoints.

You have @i(dbx) run the program until it encounters
the first breakpoint.

You examine the values of variables and expressions
to see if they meet your expectations.

You tell @i(dbx) to continue execution to the next
breakpoint, and so on.

When you have found the problem,
you exit the debugger.
@end(enumerate)

@section[@i(dbx) Commands]

The following is a list of @i(dbx's) most useful commands;
the others are documented in the @i(dbx) @i(man) page
(type @b[man dbx]).
You will see these commands in action in the next section.

@begin(description)
@b[quit]@\This command ends your @i(dbx) session
and gets you back to the shell.
You can suspend the session by typing Ctrl-Z; restart it by typing
@i(fg).

@b[help]@\This command prints a summary of @i(dbx) commands.

@b[run]@\This command tells @i(dbx) to run your program.
The program will run to completion unless it produces a fatal error,
or unless you have told @i(dbx)
to halt execution by setting breakpoints with the @b(stop) command.
If your program takes command line arguments,
add the arguments to the @i[run] command.

@b[stop]@\This command tells @i(dbx) to halt execution when the program
reaches a specified line, a specified function, or generates a specified
condition.
If you want to debug a program by suspending execution and
stepping through it line by line,
you must use this command to set at least one breakpoint.
You can use @i(stop) as follows:
@begin(description)
@b[stop at @i(sourceline)]@\@\Stop at line number @i(line) of the source code.

@b[stop in @i(function)]@\@\Stop when @i(function) is called.

@b[stop @i(variable)]@\@\Stop when the value of @i(variable) changes.
@end(description)

@b[next]@\After @i[dbx] has suspended execution,
you can use this command to execute the next line of source code.
If the next line is a function call,
@i[dbx] will execute the entire function as though it
were one line, and halt execution
at the next line of the original procedure.

@b[step]@\Like @i[next],
this command executes the next line of source code,
but @i[step] differs from @i[next] in the following way:
if the next line of source code is a function call,
@i[step] will execute the first line of source @i[within
the function], and will suspend execution at the function's
next line of source.
You will want to use @i[step] in cases where you want to examine
what happens inside specific function calls.

@b[cont]@\This command will restart execution.
The program will run to completion unless it produces a fatal error,
or it reaches a breakpoint.

@b[print]@\After @i(dbx) has stopped execution,
you can use this command to display the value of a variable or expression:
@begin(example)
@b[print]  @i[variable]

@b[print] @i[expression]
@end(example)
You can use @i(print) to display any valid C expression.

@b[dump]@\This command displays the names and values of all
currently active variables.

@b[trace]@\This command displays tracing information as @i(dbx) executes
a program:
@begin(example)
@b[trace]  @i(variable)
@end(example)
displays @i(variable's) name and value each time the program changes
@i(variable's) value.
@begin(example)
@b[trace] @i(function)
@end(example)
displays information about @i(function) each time it is called.
@i(dbx) will tell you which routine made the call,
the source line number of the call,
what parameters were passed to the function,
and what value the function returned upon completion.
@begin(example)
@b[trace] @i(expression) @b[at] @i(sourceline)
@end(example)
displays the value of the @i(expression) as the program executes
the statement at @i(sourceline).
@begin(example)
@b[trace] @i[sourceline]
@end(example)
displays the statement at @i(sourceline) before the program executes it.
Note that sometimes @i(trace) doesn't work properly.
If you try to @i[trace] an array variable in a @i[main]() procedure,
@i[dbx] itself  generates a fatal error and produces its own @i[core] file.

@b[status]@\This command lists by number the currently active @i(trace) and
@i(stop) commands.

@b[delete]@\This command cancels @i(trace) and @i(stop) commands by command
number as displayed with the @i(status) command.

@b[file]@\This is an important command if you are debugging a program
made up of multiple source files.
When used without arguments,
@i[file] prints the filename of the current source file.
When you first start the debugger the current source file is
the file that was specified first when you compiled the program.
If you compile the program like this:
@begin[example]
@b[cc -g main.c preblank.c]
@end[example]
@i[main.c] will be the current source file when you start @i[dbx].
You can use @i[file] to switch current source files as follows:
@begin[example]
file preblank.c
@end[example]
This command will switch the current file to @i[preblank.c].

@b[list]@\This command displays source code.
If you use it without arguments, @i(list) will display the
next ten lines of source code in the current source file.
You can use arguments to @i(list) to specify lines of code:
@begin(example)
@b[list  10, 30]
@end(example)
displays source code lines ten through thirty.
You can use @i[list] to display a function's source code,
but only if that function is part of the current source file.
For instance:
@begin(example)
@b[list  main]
@end(example)
displays the @i(main)() function's source code if @i[main]
is part of the current source file.
If the function is contained in another source file,
use the @i[file] command to switch source files before
using @i[list] to display the code.

@b[where]@\This command is used when you are using @i(dbx) to examine
a @i(core) file.
@i(where) displays the line of code that produced the fatal error leading
to the core dump.
Will also list all currently active function calls.
@i[where] will also tell you what breakpoint you're at if you
happen to forget.

@b[assign]@\This command lets you change the value of a program's variable
in mid-execution.
This command:
@begin[example]
assign slength = slength - 1
@end[example]
subtracts 1 from the initial value of @i[slength].

@end(description)
