17.2 debug-on-entry

当你的函数发生错误时,Emacs会自动启动调试器。

顺便提一下,你可以手动启动调试器,适用于所有版本的Emacs;其中的优势是,即使你的代码没有错误,调试器也会运行。有时候你的代码是没有bug的!

你可以通过调用 debug-on-entry 在调用函数时手动进入调试器。

输入以下命令:

M-x debug-on-entry RET triangle-bugged RET

然后,评估以下表达式:

(triangle-bugged 5)

所有版本的Emacs都会创建一个 *Backtrace* 缓冲区,并告诉你它正在开始评估 triangle-bugged 函数:

---------- Buffer: *Backtrace* ----------
Debugger entered--entering a function:
* triangle-bugged(5)
  eval((triangle-bugged 5) nil)
  eval-expression((triangle-bugged 5) nil nil 127)
  funcall-interactively(eval-expression (triangle-bugged 5) nil nil 127)
  call-interactively(eval-expression nil nil)
  command-execute(eval-expression)
---------- Buffer: *Backtrace* ----------

*Backtrace* 缓冲区中,输入 d。Emacs将评估 triangle-bugged 函数中的第一个表达式;缓冲区将如下所示:

---------- Buffer: *Backtrace* ----------
Debugger entered--beginning evaluation of function call form:
* (let ((total 0)) (while (> number 0) (setq total ...)
        (setq number ...)) total)
* triangle-bugged(5)
  eval((triangle-bugged 5))
  eval((triangle-bugged 5) nil)
  eval-expression((triangle-bugged 5) nil nil 127)
  funcall-interactively(eval-expression (triangle-bugged 5) nil nil 127)
  call-interactively(eval-expression nil nil)
  command-execute(eval-expression)
---------- Buffer: *Backtrace* ----------

现在,再次输入 d,慢慢输入八次。每次输入 d,Emacs将评估函数定义中的另一个表达式。

最终,缓冲区将如下所示:

---------- Buffer: *Backtrace* ----------
Debugger entered--beginning evaluation of function call form:
* (setq number (1= number))
* (while (> number 0) (setq total (+ total number))
        (setq number (1= number)))
* (let ((total 0)) (while (> number 0) (setq total ...)
        (setq number ...)) total)
* triangle-bugged(5)
  eval((triangle-bugged 5) nil)
  eval-expression((triangle-bugged 5) nil)
  funcall-interactively((triangle-bugged 5) nil)
  call-interactively((triangle-bugged 5) nil)
  command-execute((triangle-bugged 5))
---------- Buffer: *Backtrace* ----------

最后,在再次输入 d 两次后,Emacs将达到错误点,并且 *Backtrace* 缓冲区的前两行将如下所示:

---------- Buffer: *Backtrace* ----------
Debugger entered--Lisp error: (void-function 1=)
* (1= number)
…
---------- Buffer: *Backtrace* ----------

通过输入 d,你能够逐步执行函数。

你可以通过在 *Backtrace* 缓冲区中输入 q 来退出;这将退出跟踪,但不会取消 debug-on-entry

要取消 debug-on-entry 的效果,调用 cancel-debug-on-entry 和函数的名称,如下:

M-x cancel-debug-on-entry RET triangle-bugged RET

(如果你在Info中阅读此内容,请现在取消 debug-on-entry。)