chapter8_4 错误处理

  在Lua中,对于大多数程序都不用作任何错误处理,应用程序本身会负责这类问题。

所有的Lua活动都是由应用程序的一次调用开始的,这类调用要求Lua执行一个程序块。

执行过程中发生了错误,此调用会返回一个错误代码(nil ),这样应用程序就能采取适当的行动来处理。

如果需要在Lua中处理错误,则必须使用函数pcall来包装需要执行的代码。

假设在执行一段Lua代码时,捕获所有执行中引发的错误,那么第一步就是将这段代码封装到一个匿名函数中

然后用pcall去调用这个函数:

local ok,msg = pcall(function ()
    <some code>
    if unexcepted then error() end
    <some code>
    print(a[i])    --引发错误,a可能不是一个talbe
    <some code >
end)

if ok then -- 没有错误发生
    <regular code >
else
    <error handling code > --保护模式代码引发一个错误,需要app引起注意
end

如果function运行过程中没有发生错误,pcall返回true,和一些返回值。

否则返回false,和错误消息。

传给error函数的错误消息不一定非得是字符串,它可以是任意的lua值 。这些值也会成为pcall的返回值。

local status,err = pcall( function() error({ code = 121}) end ) --传给error的是table
print(err.code)    --> 121

有了这些机制,就可以完成所有的异常处理。通过使用error来抛出一个异常或使用pcall来捕获异常。错误消息

则可以标识出错误类型或内容。

虽然错误消息可以是任意值,但是通常使用字符串去描述什么样的错误。

当发生内部错误时,Lua就抛出一个错误消息;其他时候,错误消息就是传递给error函数的值。

只要错误消息是一个字符串,Lua就会附加一些关于错误发生位置的信息(包含文件名比如stdin,及行号)。

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

error函数还有第二个附加参数level,用于指出应由调用层级中的哪个(层)函数来报告当前的错误。

也就是说明了谁应该为此错误负责。比如一个函数,它的功能是检查传入的参数是否正确:

function foo (str)
    if type(str) ~= "string" then
        error("string expected")
    end
        <come code>
    end

然后有人这样传入错误参数地去调用:

foo({x=1})

由于foo是调用了error,所以Lua会认为是函数发生了错误。但实际上却是foo的调用者造成的错误。

为了纠正这个问题,就要告知error函数错误是发生在调用层级的第二层中(第一层是读函数)。

function foo(str)
    if type(str) ~= "string" then
        error("string expected",2)
    end
        <come code>
end

通常发生错误时,我们希望得到更多的调试信息。比如完整的调用栈,追溯到发生错误时的函数调用。

当pcall返回其错误信息时,它已经销毁了调用栈的部分内容(也就是从pcall到错误发生点的这部分调用)。

为此,我们必须在调用pcall之前保存好完整的栈信息。

xpcall很好地解决了这个问题。它接收第二个参数,一个消息处理函数。

一旦发生错误,Lua就会在调用栈展开前调用它,所以可以在这个函数中使用

debug lib去获取关于错误的额外信息了。

Lua的调试库提供了两个通用消息处理函数:

debug.debug:提供一个提示符,让用户检查错误的原因

debug.traceback:它会根据调用栈来构建一个扩展的错误消息。也可以在任何时候调用这个函数来获取当前执行的调用栈:

print (debug.trackback())

 

posted @ 2016-08-29 15:27  daiker  阅读(166)  评论(0编辑  收藏  举报