A typical Gforth error message looks like this:
in file included from \evaluated string/:-1 in file included from ./yyy.fs:1 ./xxx.fs:4: Invalid memory address >>>bar<<< Backtrace: $400E664C @ $400E6664 foo
The message identifying the error is Invalid memory address
. The
error happened when text-interpreting line 4 of the file
./xxx.fs. This line is given (it contains bar
), and the
word on the line where the error happened, is pointed out (with
>>>
and <<<
).
The file containing the error was included in line 1 of ./yyy.fs, and yyy.fs was included from a non-file (in this case, by giving yyy.fs as command-line parameter to Gforth).
At the end of the error message you find a return stack dump that can be
interpreted as a backtrace (possibly empty). On top you find the top of
the return stack when the throw
happened, and at the bottom you
find the return stack entry just above the return stack of the topmost
text interpreter.
To the right of most return stack entries you see a guess for the word
that pushed that return stack entry as its return address. This gives a
backtrace. In our case we see that bar
called foo
, and
foo
called @
(and @
had an Invalid memory
address exception).
Note that the backtrace is not perfect: We don’t know which return stack
entries are return addresses (so we may get false positives); and in
some cases (e.g., for abort"
) we cannot determine from the return
address the word that pushed the return address, so for some return
addresses you see no names in the return stack dump.
The return stack dump represents the return stack at the time when a
specific throw
was executed. In programs that make use of
catch
, it is not necessarily clear which throw
should be
used for the return stack dump (e.g., consider one throw
that
indicates an error, which is caught, and during recovery another error
happens; which throw
should be used for the stack dump?).
Gforth presents the return stack dump for the first throw
after
the last executed (not returned-to) catch
or nothrow
;
this works well in the usual case. To get the right backtrace, you
usually want to insert nothrow
or ['] false catch 2drop
after a catch
if the error is not rethrown.
Gforth
is able to do a return stack dump for throws generated
from primitives (e.g., invalid memory address, stack empty etc.);
gforth-fast
is only able to do a return stack dump from a
directly called throw
(including abort
etc.). Given an
exception caused by a primitive in gforth-fast
, you will
typically see no return stack dump at all; however, if the exception is
caught by catch
(e.g., for restoring some state), and then
throw
n again, the return stack dump will be for the first such
throw
.
gforth-fast
also does not attempt to differentiate between
division by zero and division overflow, because that costs time in every
division.