【问题标题】:Why do crosslinked defstructs cause stack overflows? [duplicate]为什么交联的 defstructs 会导致堆栈溢出? [复制]
【发布时间】:2018-07-03 00:37:45
【问题描述】:

在玩图表时,我遇到了一个我不太理解的奇怪错误。下面的代码重现了这个问题。

;; Define struct to store a node with links to other nodes.
(defstruct node properties links)

;; Make two nodes
(setf a (make-node :properties '(:name a))
      b (make-node :properties '(:name b)))

;; Create link from b to a. This works fine...
(push b (node-links a))

;; ... but this crosslink makes lisp chase its own tail for a while and then crash with a stack overflow.
(push a (node-links b))

我使用 SBCL 和 Clozure 得到了相同的结果。将*print-length* 设置为可管理的值不起作用。

所以我的问题是:为什么这段代码没有创建与循环列表相同的无限打印循环(即没有堆栈溢出并且可以使用 Ctrl-C 停止)。任何意见表示赞赏。

谢谢, 保罗

【问题讨论】:

  • 当我在 SBCL 或 CLISP(有或没有 SLIME)中运行你的代码时,我仍然可以 Ctrl+C 退出循环。我不知道为什么它在你端不可中断。
  • 我猜 Ctrl+C 最终失败了,原因很简单,因为我使用的是一台有很多打开程序的蹩脚机器,所以在机器“消化”击键之前堆就爆炸了。跨度>

标签: data-structures common-lisp sbcl clozure-cl


【解决方案1】:

*print-length* 控制列表中元素的数量。您正在寻找*print-level*。这对我来说很好。

(let ((*print-level* 3))
  (format t "~W~%" a))
;; Output: #S(NODE :PROPERTIES (:NAME A)
;;  :LINKS (#S(NODE :PROPERTIES # :LINKS #)))

或者,您可以使用*print-circle* 检测周期并以更好的方式打印它们。

(let ((*print-circle* t))
  (format t "~W~%" a))
;; Output: #1=#S(NODE :PROPERTIES (:NAME A)
;;  :LINKS (#S(NODE :PROPERTIES (:NAME B) :LINKS (#1#))))

在这里,它实际上检测到循环并打印#1#,这是对#1= 的引用,以表明它是同一个对象。

【讨论】:

    猜你喜欢
    • 2014-12-20
    • 2011-10-22
    • 1970-01-01
    • 2018-07-01
    • 2010-09-11
    • 1970-01-01
    • 2011-01-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多