第一版是针对 Lua 5.0 编写的。虽然在很大程度上仍然适用于更高版本,但有一些区别。
第四版针对 Lua 5.3,可在 亚马逊 和其他书店购买。
购买本书,您还可以帮助支持 Lua 项目


8.5 – 错误消息和回溯

尽管您可以使用任何类型的变量作为错误消息,但通常错误消息是描述出错情况的字符串。当出现内部错误(例如尝试对非表值进行索引)时,Lua 会生成错误消息;否则,错误消息是传递给 error 函数的值。无论哪种情况,Lua 都会尝试添加有关错误发生位置的一些信息

    local status, err = pcall(function () a = 'a'+1 end)
    print(err)
     --> stdin:1: attempt to perform arithmetic on a string value
    
    local status, err = pcall(function () error("my error") end)
    print(err)
     --> stdin:1: my error
位置信息给出了文件名(示例中为 stdin)加上行号(示例中为 1)。

error 函数有一个附加的第二个参数,它给出了应该报告错误的级别;有了它,您可以将错误归咎于其他人。例如,假设您编写了一个函数,其第一个任务是检查是否正确调用了它

    function foo (str)
      if type(str) ~= "string" then
        error("string expected")
      end
      ...
    end
然后,有人用错误的参数调用了您的函数
    foo({x=1})
Lua 将矛头指向您的函数---毕竟,是 foo 调用了 error---而不是真正的罪魁祸首,即调用者。要纠正这一点,您需要通知 error 您报告的错误发生在调用层次结构的第 2 级(第 1 级是您自己的函数)
    function foo (str)
      if type(str) ~= "string" then
        error("string expected", 2)
      end
      ...
    end

通常,当错误发生时,我们希望获得比错误发生位置更多的调试信息。至少,我们希望获得一个回溯,显示导致错误的完整调用堆栈。当 pcall 返回其错误消息时,它会销毁堆栈的一部分(从它到错误点的那部分)。因此,如果我们想要一个回溯,我们必须在 pcall 返回之前构建它。为此,Lua 提供了 xpcall 函数。除了要调用的函数之外,它还接收第二个参数,即错误处理函数。如果发生错误,Lua 会在堆栈展开之前调用该错误处理程序,以便它可以使用调试库来收集有关错误的任何其他所需信息。两个常见的错误处理程序是 debug.debug,它会给你一个 Lua 提示,以便你可以自己检查错误发生时的情况(稍后我们将详细讨论,当我们讨论调试库时);以及 debug.traceback,它会构建一个带有回溯的扩展错误消息。后者是独立解释器用于构建其错误消息的函数。你也可以随时调用 debug.traceback 来获取当前执行的回溯

    print(debug.traceback())