https://www.cnblogs.com/NewMan13/p/7860404.html
转载:http://blog.csdn.net/yuanfengyun/article/details/53454488
1、基本概念
lua本质上利用C函数来操作LUA虚拟机。LUA虚拟机对于C来说只是在堆上的内存对象。
lua有自己的运行对象(协程),每个协程有自己的调用栈。
比如下面的函数:
function add(x, y)
return x + y
end
如果x或y不能进行加法操作,在调用中就会产生异常。产生了异常,虚拟机需要对异常进行处理,最简单粗暴的处理是直接退出程序。
但这样肯定是不符合一门现在语言对异常处理能力的要求。lua虚拟机的做法是把异常交给用户之前定义的异常处理函数来进行处理。比如是打印出异常信息,打印出调用栈。用户的异常处理函数处理完以后,虚拟机还需要恢复到正常的执行流程中。但是恢复到哪一层的调用栈,不同时候是不一样的。虚拟机会从上一层函数开始,直到能找到一个异常恢复点。找到异常恢复点以后,虚拟机将程序状态恢复正常,并从恢复点再次开始执行。
2、普通调用
function main()
local c = add(1, nil)
print(c)
end
假如上述main函数在调用时调用栈为
main()
add()
在add函数中出现异常,由于add的上一层没有异常恢复点,异常会继续向上抛出。后面的print语句不会被执行。
3、使用安全调用
function main()
local c
local success, c = pcall(add, x, y)
if success then
print("c is ", c)
else
print("exception accur")
end
end
上面修改过的main使用了安全调用的方式,调用add之前,生成了一个恢复点,当add中出现异常,向上抛出时,遇到了恢复点,程序恢复到了正常执行状态。当调用中没有异常发生,pcall会返回true和add的返回值;当发生异常时,pcall会返回false。
4、使用函数安全调用并使用自定义的异常处理函数
在lua.c中异常发生时,默认的异常处理函数会调用luaL_traceback。它会先打印出异常信息,然后再打印出调用栈。在lua代码中,如果需要指定自己的异常处理函数,可以使用xpcall,以第二个参数中传入自己的异常处理函数。
exp = function (msg) print(msg) end
function main()
local c
local success, c = xpcall(add, exp, x, y)
if success then
print("c is ", c)
else
print("exception accur")
end
end
在传入自己的异常处理函数之后,在发生异常时,虚拟机会调用该函数,而不是上层的处理函数。
5、主动抛出异常
在lua代码中可以简单通过error函数抛出异常。assert函数相当于对error函数进行了包装,通过条件判断是否需要抛出异常。
function add(x, y)
if type(x) ~= "number" then
error("x is not a number")
end
if type(y) ~= "number" then
error("y is not a number")
end
end
分类: lua