11. Debugging Features
When debugging a program, programmers often find it helpful to examine
the program's internal status while it runs: the values of internal
variables, the choices made in if and cond statements, and
so forth. Guile Scheme provides a debugging interface that programmers
can use to single-step through Scheme functions and examine symbol
bindings. This is different from the 35. Debugging Infrastructure, which permits
programmers to debug the Guile interpreter itself. Most programmers
will be more interested in debugging their own Scheme programs than the
interpreter which evaluates them.
[FIXME: should we include examples of traditional debuggers
and explain why they can't be used to debug interpreted Scheme or Lisp?]
11.1 Single-Step
11.2 Trace
When a function is traced, it means that every call to that
function is reported to the user during a program run. This can help a
programmer determine whether a function is being called at the wrong
time or with the wrong set of arguments.
- Function: trace function
- Enable debug tracing on
function. While a program is being run, Guile
will print a brief report at each call to a traced function,
advising the user which function was called and the arguments that were
passed to it.
- Function: untrace function
- Disable debug tracing for
function.
Example:
| | (define (rev ls)
(if (null? ls)
'()
(append (rev (cdr ls))
(cons (car ls) '())))) => rev
(trace rev) => (rev)
(rev '(a b c d e))
=> [rev (a b c d e)]
| [rev (b c d e)]
| | [rev (c d e)]
| | | [rev (d e)]
| | | | [rev (e)]
| | | | | [rev ()]
| | | | | ()
| | | | (e)
| | | (e d)
| | (e d c)
| (e d c b)
(e d c b a)
(e d c b a)
|
Note the way Guile indents the output, illustrating the depth of
execution at each function call. This can be used to demonstrate, for
example, that Guile implements self-tail-recursion properly:
| | (define (rev ls sl)
(if (null? ls)
sl
(rev (cdr ls)
(cons (car ls) sl)))) => rev
(trace rev) => (rev)
(rev '(a b c d e) '())
=> [rev (a b c d e) ()]
[rev (b c d e) (a)]
[rev (c d e) (b a)]
[rev (d e) (c b a)]
[rev (e) (d c b a)]
[rev () (e d c b a)]
(e d c b a)
(e d c b a)
|
Since the tail call is effectively optimized to a goto statement,
there is no need for Guile to create a new stack frame for each
iteration. Using trace here helps us see why this is so.
11.3 Backtrace
- Scheme Procedure: backtrace
-
- C Function: scm_backtrace ()
- Display a backtrace of the stack saved by the last error
to the current output port.
This document was generated
by Ingo Ruhnke on September, 12 2002
using texi2html