19.2.2 Edebug 的代码插桩

要使用 Edebug 调试 Lisp 代码,必须先对代码 插桩(instrument)。 插桩会在代码中插入额外逻辑,以便在合适位置调用 Edebug。

在函数定义上使用前缀参数执行 C-M-xeval-defun), 会在求值前先对定义进行插桩。(这不会修改源码本身。) 如果变量 edebug-all-defs 为非nil,则反转前缀参数的含义: 此时 C-M-x 默认会插桩, 除非 带有前缀参数。 edebug-all-defs 默认值为 nil。 命令 M-x edebug-all-defs 可切换该变量的值。

如果 edebug-all-defs 为非nil, 则 eval-regioneval-buffer 在求值时也会对定义插桩。 类似地,edebug-all-forms 控制 eval-region 是否对 所有 表达式插桩,包括非定义表达式。 这不适用于加载或迷你缓冲区中的求值。 命令 M-x edebug-all-forms 可切换该选项。

另一个命令 M-x edebug-eval-top-level-form 可对任意顶层表达式插桩,不受 edebug-all-defsedebug-all-forms 影响。 edebug-defunedebug-eval-top-level-form 的别名。

当 Edebug 处于激活状态时,命令 Iedebug-instrument-callee) 可对光标所在列表表达式调用的函数或宏进行插桩(如果尚未插桩)。 这仅在 Edebug 能找到该函数源码时有效; 因此,加载 Edebug 后,eval-region 会记录它所求值的每个定义的位置,即使没有插桩。 另见命令 i(see 跳转),它会在插桩后直接进入该调用。

Edebug 知道如何对所有标准特殊形式、带表达式参数的 interactive 形式、 匿名 lambda 表达式以及其他定义形式进行插桩。 但 Edebug 无法自行判断用户定义宏会如何处理宏调用的参数, 因此你必须通过 Edebug 规范提供相关信息;详情见 see Edebug 和 宏

当 Edebug 在会话中第一次准备插桩代码时,会运行钩子 edebug-setup-hook, 然后将其设为 nil。 你可以用它来加载与你正在使用的包相关的 Edebug 规范,且只在使用 Edebug 时加载。

如果 Edebug 在插桩时检测到语法错误,会将光标停在出错代码处并抛出 invalid-read-syntax 错误。 例如:

error→ Invalid read syntax: "Expected lambda expression"

插桩失败的一个可能原因是:某些宏定义 Emacs 尚未加载。 解决方法是先加载定义了待插桩函数的文件。

要移除定义上的插桩,只需以**不插桩**的方式重新求值该定义。 有两种求值方式永远不会插桩: 使用 load 从文件加载,以及使用迷你缓冲区的 eval-expressionM-:)。

另一种移除插桩的方法是使用命令 edebug-remove-instrumentation。 它也可以移除所有已插桩代码的插桩状态。

更多 Edebug 内部可用的求值函数见 See 表达式求值


emacs

Emacs

org-mode

Orgmode

Donations

打赏

Copyright

© 2025 Jasper Hsu

Creative Commons

Creative Commons

Attribute

Attribute

Noncommercial

Noncommercial

Share Alike

Share Alike