标签:求值 位置 lan 匿名函数 初始 栈展开 NPU 用户 返回
在 Lua 中,动态链接被视为所有其他机制的母机制
因此利用它就可以动态地加载任何其他不在 Lua 中的机制
package.loadlib
所需两个参数
loadlib
函数加载指定的库,并将其链接入 Lua
它没有调用库中的任何函数
而是将一个 C 编写的函数作为 Lua 函数返回
如果加载库或查找初始化函数时发生错误,会返回 nil
及一条错误信息
local path = "c:/lua/5.1/socket.so"
local f = package.loadlib(path, "luaopen_socket")
require
来加载 C 程序库,这个函数会搜索指定的库loadlib
加载库,并返回初始化函数Lua 是一种扩展语言,通常嵌入在应用程序中
如果发生错误时如果直接崩溃或退出,那么我们就无法捕获到错误出现在哪里
因此 Lua 只要发生一个错误,就应该结束当前程序块并返回应用程序
Lua 中任何未预期条件都会引发一个错误,如:
可以通过调用 error
函数,显式地引发发一个错误
do
print("enter a number:")
n = io.read("*number")
if not n then
error("invalid input")
end
end
-- 与上述代码等效
do
print("enter a number:")
n = assert(io.read("*number"), "invalid input")
end
assert
如果第一个参数为 true
则返回该参数false
或 nil
就会引发一个错误assert
时会对其参数求值n
是数字类型, Lua 也会进行字符串连接n = io.read()
assert(tonumber(n), "invalid input:" .. n .. " is not a number")
当一个函数遭遇了一种未预期的情况即「异常」,可以采取两种基本行为
nil
)error
)sin
传入 table
作为参数
-- 返回一个错误代码,检查 sin 函数返回值
local res = math.sin(x)
if not res then
<错误处理代码>
end
-- 调用 sin 之前,检查参数
if not tonumber(x) then
<错误处理代码>
end
通常既不检查参数也不会检查 sin
的返回值
可以停止计算,然后给出错误消息
io.open
文件不存在的情况或拒绝访问时的异常行为
一个文件存在与否可以用是否能够打开来验证
当 io.open
无法打开一个文件时,应返回 nil
,并附加一条错误消息
do
local file, msg
repeat
print("enter a file name:")
local name = io.read()
if not name then
return
end
-- io.open 第一个参数为文件路径,第二个参数为打开模式,r 为字符模式
-- io.open 成功则返回文件句柄,无法打开会返回 nil 和错误消息
file, msg = io.open(name, "r")
if not file then
print(msg)
end
until file
end
-- 等效于上述代码.错误消息时 io.open 的第二个返回值,并成为了 assert 的第二个参数
do
local file, msg
repeat
print("enter a file name:")
local name = io.read()
if not name then
return
end
file = assert(io.open(name, "r"))
until file
end
大多数情况无需在,Lua 中作任何错误处理,由调用 Lua 的应用程序来负责
因为所有的 Lua 活动都是由应用程序的一次调用而开始的
在解释器程序中发生错误时,主循环会打印错误消息,然后继续显示提示符,并等待执行后续命令
在 Lua 中处理错误,必须使用 pcall
来包裹要执行的代码, p-->意为 protect 保护的意思
pcall
可以捕获函数执行时引发的任何错误
true
以及函数调用的返回值false
以及错误消息-- 执行一段 Lua 代码,捕获所有执行中发生的错误,需先将这段代码封装到一个函数中
function foo()
<code block>
if 未预期的条件 then
error()
end
<code block>
print(a[i]) -- 潜在的错误,a 可能不是一个 table
<code block>
end
if pcall(foo) then
-- 执行 foo 时没有发生错误
<常规代码>
else
-- foo 引发了一个错误,进行错误处理
<错误处理代码>
end
调用 pcall
时可以传入一个匿名函数
「错误消息」可以是任何值,并将其传递给 error
函数,这些值也就成为 pcall
的返回值
if pcall (function ()
-- <受保护的代码>
return 20 + 10 -- 用于测试的代码 "a" + 10
end) then
-- <常规代码>
print("ok")
else
-- <错误处理代码>
print("error")
end
do
local status, err = pcall(function ()
error({code = 121})
end)
print(status, err.code)
end
error
来抛出异常pcall
来捕获异常table
的值,就会产生错误消息error
函数的值do
local status, err = pcall(function () a ="a"+1 end)
print(err)
end
do
local status, err = pcall(function ()
error("my error")
end)
print(err)
end
-- 位置信息包含文件名 stdin 及行号 3
-- stdin:3: my error
error
函数的第二个参数 level
,用于指出应有调用层级中的那个(层)函数来报告当前的错误,即谁为错误负责-- 在一个函数中,一开始就检查传入参数是否正确
do
function foo(str)
if type(str) ~= "string" then
-- 不加第二个参数,则认为是读函数时出错并报告错误, stdin:3: string expected
-- error("string expected")
-- 加上第二个参数,则认为是在调用层出错并报告错误, stdin:9: string expected
error("string expected", 2)
end
print(str)
end
foo({x = 1})
end
pcall
函数返回错误消息时,它已经销毁了调用栈的部分内容
如果要获取完整的追溯到发生错误时的函数调用情况,而不是仅仅获取到错误发生的位置,需要用到 xpcal
l 函数
xpcall
函数接受两个参数
发生错误时,Lua 会在调用栈展开前调用错误处理函数,就可以用 debug
库来获取错误的额外信息
debug.debug
,提供一个 Lua 提示符,让用户检查错误的原因debug.traceback
,根据调用栈来构建一个扩展的错误消息debug.traceback
来构建其错误消息debug.traceback
都可以获取当前执行的调用栈do
local t = {2, 4, 6, 8 ,10}
for i,v in ipairs(t) do
print(i, v)
print(debug.traceback())
end
end
标签:求值 位置 lan 匿名函数 初始 栈展开 NPU 用户 返回
原文地址:https://www.cnblogs.com/door-leaf/p/13215990.html