Common lisp 无限递归SB内核:输出对象

Common lisp 无限递归SB内核:输出对象,common-lisp,sbcl,Common Lisp,Sbcl,我使用的是drakma包,它正确地执行: (drakma:http-request "http://www.google.de") 单独使用时。但一旦我开始使用我自己编写的包,就会导致控制堆栈溢出。 回溯如下所示: ...htmlstuff..... 200 ((:DATE . "Sat, 08 Dec 2012 01:00:23 GMT") (:EXPIRES . "-1") (:CACHE-CONTROL . "private, max-age=0") (:CONTENT-TYPE .

我使用的是drakma包,它正确地执行:

(drakma:http-request "http://www.google.de")
单独使用时。但一旦我开始使用我自己编写的包,就会导致控制堆栈溢出。 回溯如下所示:

...htmlstuff.....
200
((:DATE . "Sat, 08 Dec 2012 01:00:23 GMT") (:EXPIRES . "-1")
 (:CACHE-CONTROL . "private, max-age=0")
 (:CONTENT-TYPE . "text/html; charset=ISO-8859-1")
 (:SET-COOKIE
  . "PREF=ID=5c4b30f4308d3e16:FF=0:TM=1354928423:LM=1354928423:S=1Z5pCWaGYqp7vYxW; expires=Mon, 08-Dec-2014 01:00:23 GMT; path=/; domain=.google.de,NID=66=QXQcXBWPNkcLtxxp5Hmlb7enfDS_wlNOA5bfxT-GsokTpAH4fulI8zxOIl_3IQQzeIcIodmcWDc0JC80k7-d-kOPznrhCJYACNu-zpp7wpPXypilOyjK2mebDUnUl3Xj; expires=Sun, 09-Jun-2013 01:00:23 GMT; path=/; domain=.google.de; HttpOnly")
 (:P3P
  . "CP=\"This is not a P3P policy! See http://www.google.com/support/accounts/bin/answer.py?hl=en&answer=151657 for more info.\"")
 (:SERVER . "gws") (:X-XSS-PROTECTION . "1; mode=block")
 (:X-FRAME-OPTIONS . "SAMEORIGIN") (:CONNECTION . "close"))
#<PURI:URI http://www.google.de/>
INFO: Control stack guard page unprotected
Control stack guard page temporarily disabled: proceed with caution

debugger invoked on a SB-KERNEL::CONTROL-STACK-EXHAUSTED in thread
#<THREAD "main thread" RUNNING {1002978CA3}>:
  Control stack exhausted (no more space for function call frames).
This is probably due to heavily nested or infinitely recursive function
calls, or a tail call that SBCL cannot or has not optimized away.

PROCEED WITH CAUTION.

Type HELP for debugger help, or (SB-EXT:QUIT) to exit from SBCL.

restarts (invokable by number or by possibly-abbreviated name):
  0: [ABORT] Exit debugger, returning to top level.

(SB-KERNEL::CONTROL-STACK-EXHAUSTED-ERROR)
0] 



....way more of those....
15854: ((SB-PCL::FAST-METHOD PRINT-OBJECT (T T))
        #<unavailable argument>
        #<unavailable argument>
#1#        #1=
        #<unavailable argument>)
15855: ((LABELS SB-IMPL::HANDLE-IT :IN SB-KERNEL:OUTPUT-OBJECT)
        #<SYNONYM-STREAM :SYMBOL SB-SYS:*TTY* {10001B3103}>)
15856: ((SB-PCL::FAST-METHOD PRINT-OBJECT (T T))
        #<unavailable argument>
        #<unavailable argument>
#1#        #1=
        #<unavailable argument>)
15857: ((LABELS SB-IMPL::HANDLE-IT :IN SB-KERNEL:OUTPUT-OBJECT)
        #<SYNONYM-STREAM :SYMBOL SB-SYS:*TTY* {10001B3103}>)
15858: ((SB-PCL::FAST-METHOD PRINT-OBJECT (T T))
        #<unavailable argument>
        #<unavailable argument>
#1#        #1=
        #<unavailable argument>)
15859: ((LABELS SB-IMPL::HANDLE-IT :IN SB-KERNEL:OUTPUT-OBJECT)
        #<SYNONYM-STREAM :SYMBOL SB-SYS:*STDOUT* {10001DCB03}>)
15860: #1#(PRIN1 #1= NIL)
15861: (SB-IMPL::REPL-FUN NIL)
15862: ((LAMBDA () :IN SB-IMPL::TOPLEVEL-REPL))
15863: (SB-IMPL::%WITH-REBOUND-IO-SYNTAX
        #<CLOSURE (LAMBDA # :IN SB-IMPL::TOPLEVEL-REPL) {10076F355B}>)
15864: (SB-IMPL::TOPLEVEL-REPL NIL)
15865: (SB-IMPL::TOPLEVEL-INIT)
15866: ((FLET #:WITHOUT-INTERRUPTS-BODY-236911 :IN SAVE-LISP-AND-DIE))
15867: ((LABELS SB-IMPL::RESTART-LISP :IN SAVE-LISP-AND-DIE))
wheras
(rstyl:LOG-ERROR err)
是一个宏,扩展为:

(WRITE ERR :ESCAPE NIL :STREAM A-PACKAGE:*LOG-STREAM-ERROR*)
*LOG-STREAM-ERROR*
的值为:
#

这句台词怎么能产生如此巨大的影响呢?

事实上,几乎没有什么东西

简单错误
是一种定义用于打印它的特殊插槽的条件,
:format control
:format arguments
。不幸的是,它们的实用性很小,因为您既不能在子条件的定义中覆盖它们,也不能在任何初始化后挂钩中覆盖它们,因为没有。总的来说,我发现
简单错误
的用处非常有限,因为它不能只捕获需要打印的消息,而必须在每次创建此条件的实例时提供消息

因此,如果要扩展
简单错误
,可以执行以下操作:

(define-condition recepie-action-errornous (simple-error) ()
  (:report
   (lambda (condition stream)
     (declare (ignore condition))
     (format stream "Erroneous recepie action happened"))))
然后,您的日志记录可以如下所示:

(write (make-condition 'recepie-action-errornous) :escape nil)
它将打印
“错误接收操作已发生”
消息。还不错,但您并没有使用将此条件与其祖先区分开来的唯一功能,
条件
条件,即打印格式化输出的能力


换句话说,我并不认为你在扩展简单错误方面有什么意义,我认为它主要是根据你在构建它时给出的参数来促进报告,但是如果你不给出任何参数,那就有点浪费了

简单错误
是一种定义用于打印它的特殊插槽的条件,
:format control
:format arguments
。不幸的是,它们的实用性很小,因为您既不能在子条件的定义中覆盖它们,也不能在任何初始化后挂钩中覆盖它们,因为没有。总的来说,我发现
简单错误
的用处非常有限,因为它不能只捕获需要打印的消息,而必须在每次创建此条件的实例时提供消息

因此,如果要扩展
简单错误
,可以执行以下操作:

(define-condition recepie-action-errornous (simple-error) ()
  (:report
   (lambda (condition stream)
     (declare (ignore condition))
     (format stream "Erroneous recepie action happened"))))
然后,您的日志记录可以如下所示:

(write (make-condition 'recepie-action-errornous) :escape nil)
它将打印
“错误接收操作已发生”
消息。还不错,但您并没有使用将此条件与其祖先区分开来的唯一功能,
条件
条件,即打印格式化输出的能力


换句话说,我看不出你在扩展
简单错误方面有什么意义,我认为它的主要功能是根据你在构建它时给出的参数来促进报告,但如果你不给出任何参数,那就有点浪费了。

奇怪的是,在调用这个简单的示例
(drakma:http请求)时,我没有使用日志例程http://www.google.de“”
因此,在加载包时,我实际上必须覆盖关键代码。我这样做了,但在回溯或输出中找不到函数liset。但是我重写了这个方法,跳过了日志部分,错误就不再发生了。因此,导致这一行的原因是:
(WRITE ERR:ESCAPE NIL:STREAM A-PACKAGE:*LOG-STREAM-ERROR*)
我一读到这一行就意识到了这一点。谢谢,请将其作为答案发布。奇怪的是,我在调用这个简单的示例
(drakma:http请求)时没有使用日志例程http://www.google.de“”
因此,在加载包时,我实际上必须覆盖关键代码。我这样做了,但在回溯或输出中找不到函数liset。但是我重写了这个方法,跳过了日志部分,错误就不再发生了。因此,导致这一行的原因是:
(WRITE ERR:ESCAPE NIL:STREAM A-PACKAGE:*LOG-STREAM-ERROR*)
我一读到这一行就意识到了这一点。谢谢,请将其作为答案发布。