This question already has an answer here:
Closed 2 years ago.
Unusual stack overflow when inserting nodes in binary tree
(1个答案)
我仍在将代码从Franz Lisp移植到Common Lisp现在我好像把翻译推到了一个奇怪的角落里。
[11]> (setq fff (cadr contextstack))
*** - Program stack overflow. RESET

那怎么会导致堆栈溢出呢递归在哪里?
我可以选择长度:
[12]> (length contextstack)
79

describe有效。这只是长“描述”输出的开始。
[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

但是,应用于contextstack的几乎任何其他内容都会因堆栈溢出消息而崩溃。
该结构包含到其他ENODE项的链接,并且存在可使某些代码循环的循环性。但是ENODE怎么样
甚至可能?
最初的代码使用的是“hunks”,这是20世纪70年代MacLISP的一个特性,我把它转换成使用常见的LISP结构,可能已经破坏了一些东西。
这些都是解释性的,我什么都没编译。默认为安全级别我试图添加cadr来强制进行更多的检查,但没有改变任何东西。
如果您想复制此代码,请下载
https://github.com/John-Nagle/pasv/tree/master/src/CPC4
启动“clisp”,执行(proclaim '(optimize (safety 3))),然后开始查看(load 'setup)当程序初始化时,任何中断都会提前发生。

最佳答案

你怎么会犯错误
很可能,错误是在打印中,而不是cadr你可以通过做

(progn (cadr contextstack) nil)

这应该行得通。
如果它仍然爆炸,则应检查cadr是否引发异常(然后错误消息将包含循环对象并爆炸):
(and (consp contextstack)
     (consp (cdr contextstack)))

如何避免错误
CLISP FAQ说:
当您试图打印循环对象(LISTSTRUCTURE-OBJECTVECTOR等)并且*PRINT-CIRCLE*NIL时,总是会出现堆栈溢出只需将*PRINT-CIRCLE*设置为T
注意,这不是CLISP特有的,当*print-circle*nil时,您应该会得到与任何ANSI Common Lisp相同的错误。
在您的具体案例中,仔细查看(describe (cadr contextstack))的输出:
(# . #1=#)是一个缺点。
This #= notation用于
打印圆形对象时避免堆栈溢出的打印机。
注:-)

关于lisp - Clisp“程序堆栈溢出。 (cadr)上的“RESET”。怎么样? ,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/41796893/

10-11 01:32