Debugging with GDB
Here's information on the gdb debugger.  See "man gdb" for a complete
description of gdb's command.  Other debuggers exist, including dbx,
but those won't be covered.
To compile your program for gdb, compile each source file prog.c as
        gcc -g prog.c
The "-g" causes symbol table information and some other stuff to be
included in the executable file, in order to allow you to use symbol
names when debugging.  If you're using a Makefile, just add the
following line at the top and replace every occurrence of `gcc' with
`$(CC)'.
        CC = gcc -g
You can run your program from gdb, as follows:
	% gdb a.out
	(gdb) run
If you're familiar with Emacs, you can run gdb from within Emacs with
"M-x gdb" (type "C-h m" to see useful key bindings).  This is much
better than running gdb from the Unix prompt, since Emacs shows you
where you are in the code.
Consider the program 
       bad-bst.c,
which implements a binary search tree of integers and accepts commands
from the input to insert, delete, seek, and print.  I have introduced
a small bug into this program.  Following is the debugging session
with some comments added.
You should copy bad-bst.c into your own account (click on the pointer
above) and do these same steps, first running gdb from the Unix
prompt.  Only then should you run gdb from within Emacs; things will
be somewhat different than described below.
% gcc -g bad-bst.c                   /* Compile with debugging stuff       */
% a.out                              /* Run a.out                          */
i 1                                  /* Try to insert a 1 into the BST     */
Segmentation fault (core dumped)
% gdb a.out                          /* Run the debugger on your program   */
... GDB introductory message ...
(gdb) run                            /* Run a.out again, from within gdb   */
Starting program: a.out 
i 1                                  /* Try to insert a 1 into the BST     */
                                     /* (YOU TYPE THIS "i 1")              */
Program received signal SIGSEGV, Segmentation fault.
0x10e80 in BST_insert (k=1) at bad-bst.c:176
176         if (k < y->key)
(gdb) where                          /* Show a stack trace: we are now at  */
                                     /* BST_insert (called with k=1), on   */
                                     /* line 176 of bad-bst.c.  This       */
                                     /* was called from line 78 in main(). */
#0  0x10e80 in BST_insert (k=1) at bad-bst.c:176
#1  0x10c0c in main (argc=1, argv=0xeffffa1c) at bad-bst.c:78
(gdb) list 170,180                   /* List the source file               */
  170   
  171     /* point tree node to new node */
  172   
  173     if (y = NULL)
  174       root = new_node;        /* tree was empty */
  175     else 
  176       if (k < y->key)
  177         y->left = new_node;   /* new node is to left of y */
  178       else
  179         y->right = new_node;  /* new node is to right of y */
  180   
                                     /* Looking at line 176, you see two   */
                                     /* potential errors, in the values of */
                                     /* "k" and "y->key".                  */
(gdb) print k                        /* Print the current value of k       */
$1 = 1                               /* k = 1                              */
(gdb) print y->key                   /* Print the current value of y->key  */
Cannot access memory at address 0x0. /* y->key is garbage, so look at y    */
(gdb) print y                        /* Print the current value of y       */
$2 = (NODE *) 0x0                    /* y = NULL pointer                   */
(gdb) quit                           /* The bug is found: y is NULL, so    */
                                     /* y->key is an invalid expression.   */
                                     /* Looking at line 173, y is NULL     */
                                     /* because the test is (y = NULL)     */
                                     /* instead of (y == NULL).            */
The program is running.  Quit anyway (and kill it)? (y or n) y
%
Some useful gdb commands are listed below.
help            - Generic help, by subject
help [command]  - Show information about [command]
run		- Run the program.  Typing ^C will bring you back to gdb.
run < [file]	- Run the program with [file] in place of the standard input.
where		- Print the procedure call stack.
list [x],[y]	- List the source file between lines [x] and [y].
print [expr]	- Evaluate and print an expression [expr].  [expr] can be
		  very complicated, and can include things like function
		  calls, pointer dereferencing (* and -]), and structure
		  accessing (.).
set [var] = [expr] - Set the value of a variable.
whatis [ident]	- Describe the type of an identifier.
break [line]	- Stop execution when [line] is reached.  There are other
		  versions of this command.  Use "help breakpoints" to see
                  them.  This particular command just sets a breakpoint.
cont		- Continue execution from where it last stopped.
step		- Execute the next line, then stop.