问题
I'm (still) porting code from Franz Lisp to Common LISP. Now I seem to have pushed the interpreter into a strange corner where it blows up.
[11]> (setq fff (cadr contextstack))
*** - Program stack overflow. RESET
Now how can that cause a stack overflow? Where's the recursion?
I can take the length OK:
[12]> (length contextstack)
79
describe
works. This is just the beginning of long "describe" output.
[13]> (describe (cadr contextstack))
(# . #1=#) is a cons.
#<FUNCTION POPPATTERN (NODE) (DECLARE (SYSTEM::IN-DEFUN POPPATTERN)) (BLOCK POPPATTERN (MAPONE # #) (XEPATTERN NODE #))> is an interpreted
function.
Argument list: (NODE)
#1=# is a structure of type ENODE.
Slots:
EROOT =
#1=#S(ENODE :EROOT #1# :EQCLASS #1# :ESUCCESSORS ALLTRUE! :ESLENGTH NIL :EPREDECESSORS NIL :ECONGRUENT NIL :EDEMON NIL :EMERGEDEMON NIL
:EPATTERN
;;; much more
But almost anything else applied to contextstack
blows up with the stack overflow message.
The structure ENODE
contains links to other ENODE
items, and there is circularity which could make some code loop. But cadr
? How is that
even possible?
The original code used "hunks", a MacLISP feature from the 1970s. I converted it to use Common LISP structs, and may have broken something.
This is all running interpretive; I haven't compiled anything. Safety level is the default. I tried adding (proclaim '(optimize (safety 3)))
to force more checking, but it didn't change anything.
If you want to reproduce this, download the code in
https://github.com/John-Nagle/pasv/tree/master/src/CPC4
start "clisp", do (load 'setup)
, and then start looking at contextstack
. Whatever is breaking is happening early, as the program is initializing.
回答1:
How you got the error
Chances are, the error is in printing, not cadr
. You can verify it by doing
(progn (cadr contextstack) nil)
which should work just fine.
If it still blows up, you should check if cadr
raises an exception (and then the error message would contain a circular object and blow up):
(and (consp contextstack)
(consp (cdr contextstack)))
How to avoid the error
CLISP FAQ says:
You will always get a stack overflow when you try to print a circular object (
LIST
,STRUCTURE-OBJECT
,VECTOR
etc) and *PRINT-CIRCLE* isNIL
. Just set*PRINT-CIRCLE*
toT
.
Note that this is not CLISP-specific, you should get the same error with any ANSI Common Lisp when *print-circle*
is nil
.
In your specific case, look closely at the output of (describe (cadr contextstack))
:
(# . #1=#) is a cons.
This #= notation is used by the printer to avoid stack overflows when printing circular objects.
PS. You now owe me 10 zorkmids :-)
来源:https://stackoverflow.com/questions/41796893/clisp-program-stack-overflow-reset-on-a-cadr-how