【问题标题】:How do I show the line number and source file of an error in SBCL?如何在 SBCL 中显示错误的行号和源文件?
【发布时间】:2020-12-16 17:24:41
【问题描述】:

我的~/.sbclrc 看起来像这样:

(sb-ext:restrict-compiler-policy 'debug 3)

(setf *debugger-hook* #'(lambda (condition original-hook)
                          (declare (ignore original-hook))
                          (print-backtrace)
                          (format *error-output* "~%~A~%" condition)
                          (finish-output *error-output*)
                          (abort)))

假设我有一个程序 my-program.lisp 包含一个错误的函数:

;; ...
(defun calculate (x)
  (/ x 0))
;; ...

如果我跑步:

$ sbcl --load my-program.lisp
* (calculate 100)

我收到此错误:

Backtrace for: #<SB-THREAD:THREAD "main thread" RUNNING {10005E85B3}>
0: (SB-KERNEL::INTEGER-/-INTEGER 100 0)
1: (CALCULATE 100)
2: (SB-INT:SIMPLE-EVAL-IN-LEXENV (CALCULATE 100) #<NULL-LEXENV>)
3: (EVAL (CALCULATE 100))
4: (INTERACTIVE-EVAL (CALCULATE 100) :EVAL NIL)
5: (SB-IMPL::REPL-FUN NIL)
6: ((LAMBDA NIL :IN SB-IMPL::TOPLEVEL-REPL))
7: (SB-IMPL::%WITH-REBOUND-IO-SYNTAX #<CLOSURE (LAMBDA NIL :IN SB-IMPL::TOPLEVEL-REPL) {10046268FB}>)
8: (SB-IMPL::TOPLEVEL-REPL NIL)
9: (SB-IMPL::TOPLEVEL-INIT)
10: ((FLET SB-UNIX::BODY :IN SAVE-LISP-AND-DIE))
11: ((FLET "WITHOUT-INTERRUPTS-BODY-36" :IN SAVE-LISP-AND-DIE))
12: ((LABELS SB-IMPL::RESTART-LISP :IN SAVE-LISP-AND-DIE))

arithmetic error DIVISION-BY-ZERO signalled
Operation was (/ 100 0).

但是运行时错误的行号和源文件在哪里呢?想象一下,如果我有数百个文件和数千个函数。知道错误的文件、行号和列号会不会有帮助?如何显示错误的行号和源文件?

我很惊讶这种编程语言在默认情况下没有这个功能,而几乎所有其他解释器和编译器都能够轻松做到这一点。

【问题讨论】:

  • 一个 new discussion 带有指向 bissect 的指针,“如果由实现提供,可以为您提供行号信息。”

标签: common-lisp sbcl


【解决方案1】:

使用 Slime(或 Sly)提供了开箱即用的此功能,但实际上这是可能的,因为底层环境已经存储了足够的信息。如果您查看代码是如何实现的(通过在 Emacs 中使用 M-. 导航,您可以看到在 SBCL 中,源代码位置部分取决于 sb-introspect

在你的例子中,加载包含calculate的文件后,如果你require这个模块,如下:

* (require 'sb-introspect)
("SB-INTROSPECT")

您可以拨打find-definition-source找到所有相关信息:

* (sb-introspect:find-definition-source #'calculate)
#S(SB-INTROSPECT:DEFINITION-SOURCE
   :PATHNAME #P"/tmp/mp.lisp"
   :FORM-PATH (2)
   :FORM-NUMBER 0
   :CHARACTER-OFFSET 51
   :FILE-WRITE-DATE 3817139822
   :PLIST NIL
   :DESCRIPTION NIL)

除了文件,SBCL 还将位置存储为字符偏移量,还存储该文件中的表单数(因此,如果您在其前面添加空格或 cmets,编辑器仍然可以找到它的位置,即使在文件被修改)。

回溯打印机功能也有更多或更少信息的选项。

【讨论】:

  • #'sb-introspect:find-definition-source提供了字符偏移量,但是有没有办法获取行号
  • @Flux 仅当您使用的编辑器无法移动到文件中的字符偏移量时,行号才重要,或者您正在使用硬拷贝进行调试。这两件事我都做过,但那是很久以前的事了。
【解决方案2】:

我通常将 SLIME + GNU Emacs 与 SBCL 一起使用。

然后我编译/加载调试级别为 3 的文件。

然后我可以在一帧的回溯窗口中按v,编辑器会跳转到源代码。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-21
    • 2011-03-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多