【问题标题】:Common Lisp - What's wrong with my debugger?Common Lisp - 我的调试器出了什么问题?
【发布时间】:2020-04-05 17:08:27
【问题描述】:

我正在尝试运行此代码:

(defparameter *digits-string* (uiop:read-file-string "day08.txt"))

(defparameter shape '(25 6))

(defun read-file-into-layers (filepath layer-w layer-h)
  (with-open-file (stream filepath)
    (do ((char (read-char stream) (read-char stream))
         (layer-size (* layer-w layer-h))
         (layers nil)
         (layer nil)
         (i nil))
        ((not (digit-char-p char)) layers)
      (when (null layer) (setf layer (make-array layer-size)
                               i 0))
      (setf (aref layer i) (digit-char-p char))
      (incf i)
      (when (= i layer-size) (progn (push layers layer)
                                    (setf layer nil
                                          i 0))))))

(https://github.com/AlbertoEAF/advent_of_code_2019/blob/d0a331157cbb3f37a16ae92f3cc2c56a35b3e00e/common-lisp/day08.lisp#L14-L28 + day08.txt for https://adventofcode.com/2019/day/8)

返回 nil,不知道为什么(文件包含一行 15k 位和一个换行符)。

我正在尝试调试:

;; 1) Set maximum debug level
(declaim (optimize (speed 0) (space 0) (debug 3)))
;; 2) Recompile the full module + C-u C-c C-c on that function (don't know if that last part is needed)
;; 3) step:
(step (READ-file-into-layers "day08.txt" 25 6))

我仍然几乎看不到任何变量,并且仅在(read-char stream)(incf i) 处停止,没有别的吗?而且几乎没有定义任何变量!

另外,如果我按“e”来计算某些表达式,即使有时某些变量不会出现在堆栈跟踪中,在这种情况下它会报告它们根本没有定义。

关于调试器为何出现这种奇怪行为的任何想法?还是只是我的代码完全被破坏了?尽管如此,调试器在这种情况下将是最有帮助的 :)

【问题讨论】:

  • 我用打印进行了调试,问题出在推送中,参数被颠倒了。不过,这不是我的意思,我的问题仍然是为什么调试器会这样做并且根本没有帮助,以及如何使其正常工作而不必用打印填充我的代码?

标签: debugging common-lisp slime


【解决方案1】:

可能是你的编译器太聪明了。当您仔细观察时,由于push 的倒数形式,您只将layerlayers 设置为nil。在某一时刻,layer 变为 (nil) 之后直接恢复为 nil。如果所有这些无操作都被抛弃,那么就没有什么可做的了。

您可以尝试通过使用disassemble 反汇编您的编译函数来收集是否是这种情况。

【讨论】:

  • 谢谢你,哇!将检查是否是这种情况并报告:)
  • @Svante 就是这种情况,但是,即使那样,我也无法逐步完成 setf 调用。假设你有这个功能(愚蠢的代码示例),你怎么能通过单步调试它?是否也可以进入 setf ? (defun f (list) (setf (elt list 0) 1) (setf (elt list 1) 2) list) (step (f (list 0 0 0 0))) ?
  • Setf 是一个宏,在这种情况下,它扩展为一些嵌套的rplaca 形式,它被编译成一些指令,但没有函数调用。
  • 所以您是说交互式调试存在一些限制,对吧?当你得到复杂的程序并且你想调试和更详细地了解正在发生的事情时,我能问一下你会做什么/建议做什么吗? (包括代码中间的宏和setf之类的调用,这可能有助于调试)?谢谢!
  • 对于宏,你所能做的就是看看它们的扩展。 Setf 是一个宏。在标准语言工具中,我主要使用tracebreak。除此之外,我尽量避免复杂性,这样我就不必一次挖掘太多。
猜你喜欢
  • 1970-01-01
  • 2010-10-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-03
  • 1970-01-01
  • 2019-01-18
  • 1970-01-01
相关资源
最近更新 更多