Warning: This is the manual of the legacy Guile 2.0 series. You may want to read the manual of the current stable series instead.
Next: Pre-Unwind Debugging, Previous: Catching Exceptions, Up: Programmatic Error Handling [Contents][Index]
The other interesting information about an error is the full Scheme stack at the point where the error occurred; in other words what innermost expression was being evaluated, what was the expression that called that one, and so on. If you want to write your code so that it captures and can display this information as well, there are a couple important things to understand.
Firstly, the stack at the point of the error needs to be explicitly
captured by a make-stack
call (or the C equivalent
scm_make_stack
). The Guile library does not do this
“automatically” for you, so you will need to write code with a
make-stack
or scm_make_stack
call yourself. (We emphasise
this point because some people are misled by the fact that the Guile
interactive REPL code does capture and display the stack
automatically. But the Guile interactive REPL is itself a Scheme
program24
running on top of the Guile library, and which uses catch
and
make-stack
in the way we are about to describe to capture the
stack when an error occurs.)
And secondly, in order to capture the stack effectively at the point
where the error occurred, the make-stack
call must be made before
Guile unwinds the stack back to the location of the prevailing catch
expression. This means that the make-stack
call must be made
within the handler of a with-throw-handler
expression, or the
optional "pre-unwind" handler of a catch
. (For the full story of
how these alternatives differ from each other, see Exceptions. The
main difference is that catch
terminates the error, whereas
with-throw-handler
only intercepts it temporarily and then allow
it to continue propagating up to the next innermost handler.)
So, here are some examples of how to do all this in Scheme and in C. For the purpose of these examples we assume that the captured stack should be stored in a variable, so that it can be displayed or arbitrarily processed later on. In Scheme:
(let ((captured-stack #f)) (catch #t (lambda () ;; Execute the code in which ;; you want to catch errors here. ...) (lambda (key . parameters) ;; Put the code which you want ;; to handle an error after the ;; stack has been unwound here. ...) (lambda (key . parameters) ;; Capture the stack here: (set! captured-stack (make-stack #t)))) ... (if captured-stack (begin ;; Display or process the captured stack. ...)) ...)
And in C:
SCM my_body_proc (void *body_data) { /* Execute the code in which you want to catch errors here. */ ... } SCM my_handler_proc (void *handler_data, SCM key, SCM parameters) { /* Put the code which you want to handle an error after the stack has been unwound here. */ ... } SCM my_preunwind_proc (void *handler_data, SCM key, SCM parameters) { /* Capture the stack here: */ *(SCM *)handler_data = scm_make_stack (SCM_BOOL_T, SCM_EOL); } { SCM captured_stack = SCM_BOOL_F; ... scm_c_catch (SCM_BOOL_T, my_body_proc, body_data, my_handler_proc, handler_data, my_preunwind_proc, &captured_stack); ... if (captured_stack != SCM_BOOL_F) { /* Display or process the captured stack. */ ... } ... }
Once you have a captured stack, you can interrogate and display its
details in any way that you want, using the stack-…
and
frame-…
API described in Stacks and
Frames.
If you want to print out a backtrace in the same format that the Guile
REPL does, you can use the display-backtrace
procedure to do so.
You can also use display-application
to display an individual
frame in the Guile REPL format.
In effect, it is the default program which is run when no commands or script file are specified on the Guile command line.
Next: Pre-Unwind Debugging, Previous: Catching Exceptions, Up: Programmatic Error Handling [Contents][Index]