Lua错误处理

程序运行中进行错误处理是必须的。任何语言在运行过程中都会出现不可预期的错误,如果不注重错误处理,就有可能会造成信息泄露,程序无法正常运行等情况。

一、错误类型

在任何语言中,都会出现错误。Lua的错误类型有语法错误、运行错误。

1.1、语法错误

1.2、运行错误

二、抛出错误

2.1、error函数

error函数用于显示的抛出一个错误,它会终止正在执行的程序,并输出错误信息。需要注意的是,error函数永远不会返回(因此它直接中断了程序)。其语法如下:

1
error(message [,level])

其中,message就是要输出的错误信息。在输出错误信息的,error函数会在message前插入一些错误位置信息,而level参数(默认为1)就是用来定义如何获取错误位置信息的:

  • level=0:表示不获取错误位置信息。

  • level=1:表示获取error函数的位置信息(文件名+行号)。

  • level=2:表示获取error函数调用者的位置信息(文件名+行号)。

下面,我们来看一个具体的例子,示例代码如下:

1
2
3
4
5
6
local function func()
error("here is my error", 0)
end

print('==== error level is 0 ====')
func()

当level为0时,执行结果为:

1
2
3
4
5
6
7
==== error level is 0 ====
luajit: here is my error
stack traceback:
[C]: in function 'error'
test.lua:2: in function 'func'
test.lua:6: in main chunk
[C]: at 0x55f390ecd440

当level为1时,执行结果为:

1
2
3
4
5
6
7
==== error level is 1 ====
luajit: test.lua:2: here is my error
stack traceback:
[C]: in function 'error'
test.lua:2: in function 'func'
test.lua:6: in main chunk
[C]: at 0x55db23316440

当level为2时,执行结果为:

1
2
3
4
5
6
7
==== error level is 2 ====
luajit: test.lua:6: here is my error
stack traceback:
[C]: in function 'error'
test.lua:2: in function 'func'
test.lua:6: in main chunk
[C]: at 0x559c71e57440

2.2、assert函数

assert函数用于对传入的参数进行断言。我们先来看一下assert函数的语法格式,如下:

1
assert (v [, message])

当参数v为nil或false时,调用error函数;否则,传入什么就返回什么。message为调用error函数时传入的参数,默认为"assertion failed!"。我们来看如下示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
local function func()
return true
end

local ret = assert(func)
print(type(ret))

local ret = assert(func())
print(type(ret))

local ret = assert(nil)
print("here is error")

执行结果如下:

1
2
3
4
5
6
7
function
boolean
luajit: test.lua:11: assertion failed!
stack traceback:
[C]: in function 'assert'
test.lua:11: in main chunk
[C]: at 0x56451c2ba440

三、捕获错误

在Lua中。处理错误可以使用pcall和xpcall包装需要执行的代码。

3.1、pcall函数

pcall接收一个函数和要传递给该函数的参数,并执行。如果没有错误,返回true;如果有错误,返回false和errorinfo。其语法如下:

1
pcall (f [, arg1, ···])

pcall会以一种“保护模式”调用传入的函数,因此,pcall可以捕获函数执行中的任意错误。我们来看下面的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
local function func(i)
print(i)
end

local ok, err = pcall(func, 33)
print(ok, err)


local function func(i)
print(i)
error('error ...')
end

local ok, err = pcall(func, 33)
print(ok, err)

其执行结果为:

1
2
3
4
33
true nil
33
false test.lua:11: error ...

3.2、xpcall函数

在发生错误时,我们通常希望获取更多的调试信息,而不仅仅是发生错误的位置。但pcall返回时,已经销毁了调用栈的内容。因此,Lua提供了xpcall函数,它能接收两个函数:一个执行函数,一个错误处理函数。其语法如下:

1
xpcall (f, msgh [, arg1, ···])

当发生错误时,xpcall会在调用栈查看引起错误的调用,所以,可以在这个函数中使用debug.traceback获取关于错误的额外信息。我们来看如下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
local function handler(err)
print("ERROR: ", err)
print(debug.traceback())
end

local function func()
n = 1 / 1
end

status = xpcall(func, handler)
print(status)


local function func()
n = 1 / nil
end

status = xpcall(func, handler)
print(status)

其执行结果为:

1
2
3
4
5
6
7
8
9
true
ERROR: test.lua:15: attempt to perform arithmetic on a nil value
stack traceback:
test.lua:3: in function '__div'
test.lua:15: in function <test.lua:14>
[C]: in function 'xpcall'
test.lua:18: in main chunk
[C]: at 0x563ac1f67440
false

Lua错误处理
https://kuberxy.github.io/2020/12/14/Lua错误处理/
作者
Mr.x
发布于
2020年12月14日
许可协议