overflow - Wumpus游戏的make-city-edges函数导致堆溢出

标签 overflow common-lisp heap-memory sbcl land-of-lisp

翻阅《Land of Lisp》一书,我成功地了解了 Grand Theft Wumpus 游戏,它让我定义了一个 make-city-edges 函数。然而,当我尝试运行它时,SBCL 挂起一段时间,然后给我一个非常讨厌的错误,提示

    Heap exhausted during garbage collection: 0 bytes available, 16 requested.
 Gen StaPg UbSta LaSta LUbSt Boxed Unboxed LB   LUB  !move  Alloc  Waste   Trig    WP  GCs Mem-age
   0:     0     0     0     0     0     0     0     0     0        0     0 10737418    0   0  0.0000
   1:     0     0     0     0     0     0     0     0     0        0     0 10737418    0   0  0.0000
   2: 27757     0     0     0 19204    70     0    10    54 631392704 505408  2000000    0   0  0.9800
   3:     0     0     0     0     0     0     0     0     0        0     0  2000000    0   0  0.0000
   4:     0     0     0     0     0     0     0     0     0        0     0  2000000    0   0  0.0000
   5:     0     0     0     0     0     0     0     0     0        0     0  2000000    0   0  0.0000
   6:     0     0     0     0  1638   251     0     0     0 61898752     0  2000000 1523   0  0.0000
   Total bytes allocated    = 1073069936
   Dynamic-space-size bytes = 1073741824
GC control variables:
   *GC-INHIBIT* = true
   *GC-PENDING* = true
   *STOP-FOR-GC-PENDING* = false
fatal error encountered in SBCL pid 85448(tid 140735276667664):
Heap exhausted, game over.

Error opening /dev/tty: Device not configured
Welcome to LDB, a low-level debugger for the Lisp runtime environment.
ldb> 

我已经检查了三次,看看我是否犯了任何错误,但我找不到任何错误。

这是导致问题的函数:

(defun make-city-edges ()
  (let* ((nodes (loop for i from 1 to *node-num*
                      collect i))
         (edge-list (connect-all-islands nodes (make-edge-list)))
         (cops (remove-if-not (lambda (x)
                                (zerop (random *cop-odds*)))
                              edge-list)))
    (add-cops (edges-to-alist edge-list) cops)))

[here ] 是其余代码,如果您想查看其他函数,我将其添加到 GitHub Gist 页面,因为它会占用问题中太多空间。

我可以做什么来解决这个问题?我在项目中使用 OSX 10.9 上的 Emacs 24.4 (9.0) 以及 SLIMESBCL 1.2.10 .

最佳答案

在链接代码中,

(defun find-islands (nodes edge-list)
  "returns a list of nodes that aren't interconnected"
  (let ((islands nil))
    (labels ((find-island (nodes)
           (let* ((connected (get-connected (car nodes) edge-list))
              (unconnected (set-difference nodes connected)))
         (push connected islands)
         (when connected
           (find-island unconnected)))))
      (find-island nodes))
    islands))

(连接时应为(未连接时

调试堆耗尽的一些技巧:

  1. 检查循环和递归是否确实终止。 (这就是我们找到这个解决方案的原因 - get-connected 永远不会返回 nil,因此 find-island 将永远递归。)
  2. CL 的 trace 以及传统的添加 print 语句都非常有用。
  3. C-c C-c 在 SLIME 中,程序运行一段时间后但在堆耗尽之前可能会提供有用的回溯。

例如回溯:

  0: ((:INTERNAL TRAVERSE GET-CONNECTED) NIL)
      Locals:
        NODE = NIL
        #:G11908 = ((2 . 21) (20 . 22) (22 . 20) (9 . 28) (28 . 9) (2 . 7) ...)
        EDGE-LIST = ((8 . 3) (3 . 8) (18 . 7) (7 . 18) (26 . 23) (23 . 26) ...)
        VISITED = (NIL)
  1: (GET-CONNECTED NIL ((8 . 3) (3 . 8) (18 . 7) (7 . 18) (26 . 23) (23 . 26) ...))
      Locals:
        NODE = NIL
        EDGE-LIST = ((8 . 3) (3 . 8) (18 . 7) (7 . 18) (26 . 23) (23 . 26) ...)
        VISITED = (NIL)
  2: ((:INTERNAL FIND-ISLAND FIND-ISLANDS) NIL)
      Locals:
        NODES = NIL
        ISLANDS = ((NIL) (NIL) (NIL) (NIL) (NIL) (NIL) ...)
        EDGE-LIST = ((8 . 3) (3 . 8) (18 . 7) (7 . 18) (26 . 23) (23 . 26) ...)
  3: (FIND-ISLANDS (1 2 3 4 5 6 ...) ((8 . 3) (3 . 8) (18 . 7) (7 . 18) (26 . 23) (23 . 26) ...))
      Locals:
        NODES = (1 2 3 4 5 6 ...)
        EDGE-LIST = ((8 . 3) (3 . 8) (18 . 7) (7 . 18) (26 . 23) (23 . 26) ...)
        ISLANDS = ((NIL) (NIL) (NIL) (NIL) (NIL) (NIL) ...)

这可能会让我们说“我不认为节点会是nil,而岛屿会是( (nil) (nil) (nil) ...) 似乎坏了。”

关于overflow - Wumpus游戏的make-city-edges函数导致堆溢出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29589981/

相关文章:

lambda - Lisp 奇怪的段错误可能是 eval 错误

lisp - 关于 Common Lisp 作用域的微妙之处(动态与词法)

Java 虚拟机堆调优参数

c - 使用 malloc(sizeof()) 从 *void 到 *int [-fpermissive] 的无效转换

css - 溢出:隐藏不适用于伪元素

reporting-services - 在 SSRS 中用省略号截断文本框内容

lisp - asdf :load-system? 系统名是否必须与文件名一致

css - 溢出时保持div彼此相邻 float

css - 溢出:在 SVG 上可见

C++堆损坏: Local heap variable causing issues