更多信息 进群了解
QQ群:756167961
目录
- 1. `debug.debug()`
- 2. `debug.gethook([thread])`
- 3. `debug.getinfo([thread,] func [, what])`
- 4. `debug.getlocal([thread,] level, idx)`
- 5. `debug.getmetatable(value)`
- 6. `debug.getregistry()`
- 7. `debug.getupvalue(f, idx)`
- 8. `debug.getuservalue(u)`
- 9. `debug.sethook([thread,] hook, mask [, count])`
- 10. `debug.setlocal([thread,] level, idx, value)`
- 11. `debug.setmetatable(value, mt)`
- 12. `debug.setupvalue(f, idx, value)`
- 13. `debug.setuservalue(u, value)`
- 14. `debug.traceback([thread,] [msg [, level]])`
- 15. `debug.upvalueid(f, idx)`
- 16. `debug.upvaluejoin(f1, idx1, f2, idx2)`
- 总结
Lua 的 debug
库提供了一系列用于调试和运行时内省的工具函数。以下是常用函数的详细说明及示例:
1. debug.debug()
- 作用:启动交互式调试控制台,允许手动输入调试命令(如查看变量、控制执行流)。
- 注意:实际开发中较少直接使用,通常依赖外部调试器。
- 示例:
function test() debug.debug() -- 进入调试控制台 end test() -- 输入命令如 `print(a)` 查看变量
2. debug.gethook([thread])
- 作用:获取当前线程(或指定线程)的钩子设置。
- 返回值:钩子函数、钩子掩码(事件类型)、钩子触发计数。
- 钩子掩码:
'c'
:调用事件。'r'
:返回事件。'l'
:行事件(执行新行时触发)。
- 示例:
local hook, mask, count = debug.gethook() print(mask) --> 当前钩子的事件类型(如 'clr')
3. debug.getinfo([thread,] func [, what])
- 作用:用于获取函数的相关信息。
函数参数
thread
:可选参数,是一个线程对象。若提供了该参数,函数会获取此线程内指定函数的信息;若未提供,默认使用当前线程。func
:必选参数,既可以是一个函数,也可以是一个返回函数调用信息的栈层次索引(整数)。若为栈层次索引,1
代表当前函数,2
代表调用当前函数的函数,依此类推。what
:可选参数,是一个字符串,用于指定要获取的信息类型。该字符串可由以下字符组合而成:"n"
:获取函数的名称和其所属的表域名称。"f"
:返回函数本身。"S"
:获取函数的一些静态信息,像函数的源文件、起始行和结束行等。"l"
:获取函数调用发生的行号。"u"
:获取函数的上值(upvalue)数量。"t"
:判断函数是否为 C 函数,若是则返回"C"
,否则返回nil
。"L"
:获取一个表,表中记录了函数中哪些行是有效的(即会被执行的)。
返回值
此函数返回一个包含信息的表(如 source
、linedefined
)。表中的字段会依据 what
参数的不同而有所变化。以下是可能出现的字段:
name
:函数名。namewhat
:函数名称的类型,如"global"
、"upvalue"
等。func
:函数本身。source
:函数定义所在的源文件,若函数是在字符串中定义的,该字段会以@
开头。short_src
:源文件的简短名称。linedefined
:函数定义的起始行号。lastlinedefined
:函数定义的结束行号。currentline
:函数调用发生的行号。nups
:函数的上值数量。istailcall
:是否为尾调用。what
:函数的类型,如"Lua"
、"C"
、"main"
等。activelines
:一个表,记录函数中哪些行是有效的。nparams
:函数参数个数。ntransfer
:ftransfer
:isvararg
:
示例代码
local info = debug.getinfo(print)
print(info.source) --> [C](表示 C 函数)
function foo()
local info = debug.getinfo(1) -- 获取当前函数信息
print(info.currentline) --> 4(行号)
end
foo()
function exampleFunction()
local info = debug.getinfo(exampleFunction, "nSlu")
print("Function name: ", info.name)
print("Source file: ", info.source)
print("Line defined: ", info.linedefined)
print("Current line: ", info.currentline)
print("Number of upvalues: ", info.nups)
end
exampleFunction()
4. debug.getlocal([thread,] level, idx)
- 作用:获取指定堆栈帧的局部变量名和值。
- 参数:
level
:堆栈层级(0 为当前函数)。idx
:局部变量索引(从 1 开始)。
- 返回值:变量名和值(若存在)。
- 示例:
function test(a, b) local x = 10 local name, value = debug.getlocal(1, 3) -- 第三个局部变量 print(name, value) --> "x", 10 end test(1, 2)
5. debug.getmetatable(value)
- 作用:获取值的元表,忽略
__metatable
的保护。 - 对比:普通
getmetatable
会受__metatable
限制。 - 示例:
local t = {} setmetatable(t, { __metatable = "protected" }) print(getmetatable(t)) --> "protected" print(debug.getmetatable(t)) --> table:...
6. debug.getregistry()
- 作用:返回全局注册表(一个普通 Lua 表),用于 C 和 Lua 间共享数据。
- 注意:直接操作注册表可能导致不可预期行为。
- 示例:
local reg = debug.getregistry() reg.my_global_data = "secret"
7. debug.getupvalue(f, idx)
- 作用:获取函数
f
的第idx
个上值(闭包捕获的外部变量)的名称和值。 - 示例:
local x = 5 local f = function() return x + 1 end local name, value = debug.getupvalue(f, 1) print(name, value) --> "x", 5
8. debug.getuservalue(u)
- 作用:获取
userdata
或线程关联的 Lua 值。 - 示例:
local ud = newproxy(true) -- 创建 userdata(需Lua 5.1) debug.setuservalue(ud, "data") print(debug.getuservalue(ud)) --> "data"
9. debug.sethook([thread,] hook, mask [, count])
- 作用:设置钩子函数,在指定事件(调用、返回、行执行)时触发。
- 示例:
local function hook(event) print("Event:", event) end debug.sethook(hook, "crl", 2) -- 每执行 2 条指令触发
10. debug.setlocal([thread,] level, idx, value)
- 作用:修改指定堆栈帧的局部变量的值。
- 示例:
function test() local a = 10 debug.setlocal(1, 1, 20) -- 修改第一个局部变量 print(a) --> 20 end test()
11. debug.setmetatable(value, mt)
- 作用:强制设置值的元表,绕过
__metatable
保护。 - 示例:
local t = {} setmetatable(t, { __metatable = "protected" }) debug.setmetatable(t, { __index = { x = 1 } }) print(t.x) --> 1
12. debug.setupvalue(f, idx, value)
- 作用:修改函数
f
的上值。 - 示例:
local x = 5 local f = function() return x end debug.setupvalue(f, 1, 10) print(f()) --> 10
13. debug.setuservalue(u, value)
- 作用:设置
userdata
或线程的关联值。 - 示例:
local ud = newproxy(true) debug.setuservalue(ud, { key = "value" }) print(debug.getuservalue(ud).key) --> "value"
14. debug.traceback([thread,] [msg [, level]])
- 作用:生成当前堆栈跟踪的字符串,用于调试错误。
- 示例:
function foo() error(debug.traceback("Oops")) end pcall(foo) --> 输出包含堆栈跟踪的错误信息
15. debug.upvalueid(f, idx)
- 作用:返回函数
f
的第idx
个上值的唯一标识符。 - 用途:检测两个闭包是否共享同一个上值。
- 示例:
local x = 10 local f1 = function() return x end local f2 = function() return x end print(debug.upvalueid(f1, 1) == debug.upvalueid(f2, 1)) --> true
16. debug.upvaluejoin(f1, idx1, f2, idx2)
- 作用:让
f1
的第idx1
个上值与f2
的第idx2
个上值共享。 - 示例:
local x, y = 1, 2 local f1 = function() return x end local f2 = function() return y end debug.upvaluejoin(f1, 1, f2, 1) -- 共享上值 x = 100 print(f2()) --> 100(因为 y 的上值已与 x 绑定)
总结
- 调试核心:
getinfo
、getlocal
、setupvalue
用于检查或修改运行时状态。 - 钩子机制:
sethook
和gethook
用于监控程序执行流。 - 元表和注册表:
getmetatable
、setmetatable
、getregistry
操作底层数据。 - 注意事项:
- 生产环境慎用
debug
库,可能引发性能或安全问题。 - 修改运行时状态(如
setlocal
)需谨慎,易导致不可预测行为。 - 部分函数(如
upvaluejoin
)适用于高级场景,需深入理解闭包机制。
- 生产环境慎用