调试库
DEBUG调试工具:调用栈回溯、钩子、上值检查 | 本页 14 个接口。登录全站学员账号后:给函数打 ✓ 记录学习进度、写私人备注。
进入交互式调试器(逐行读执行用户输入的 Lua 语句),输入 cont 结束。服务器环境基本不可用。
无参数
无
-- debug.debug() -- 需要控制台交互环境
返回对象 o 的环境表(功能同 getfenv,但可对任意对象使用)。
| 参数 | 说明 |
|---|---|
| o | 任意对象 |
环境表
print(debug.getfenv(print) == _G) --> true
返回当前线程的钩子函数、钩子掩码和计数。
| 参数 | 说明 |
|---|---|
| thread | 协程,省略为当前 |
钩子函数, 掩码字符串, 计数
print(debug.gethook())
查询函数信息表:name 源名、source 源文件(@开头)、currentline 当前行、nups 上值数、func 函数本体等。排查“这段代码在哪个文件”很好用。
| 参数 | 说明 |
|---|---|
| thread | 协程,可选 |
| function 或 level | 函数或栈层级 |
| what | 要查的字段串,默认全部 |
信息表
local info = debug.getinfo(1, 'Sl') print(info.source, info.currentline) -- 当前文件与行号
返回栈上 level 层第 local 个局部变量的名字和值。
| 参数 | 说明 |
|---|---|
| thread | 协程,可选 |
| level | 栈层级 |
| local | 局部变量序号 |
变量名, 值
local function f()
local hp = 100
print(debug.getlocal(1, 1)) --> hp 100
end
f()绕过 __metatable 保护直接取元表(getmetatable 的强制版)。
| 参数 | 说明 |
|---|---|
| object | 任意对象 |
元表 或 nil
local t = setmetatable({}, {__metatable = 'locked'})
-- print(getmetatable(t)) --> locked
print(type(debug.getmetatable(t))) --> table返回注册表(Lua 虚拟机的全局共享表,C API 数据都登记在这里)。高级用途,业务脚本不要动。
无参数
注册表
local reg = debug.getregistry() print(type(reg)) --> table
返回函数 f 的第 up 个上值(闭包捕获的外部局部变量)的名字和值。查看/修改闭包内部状态的黑科技。
| 参数 | 说明 |
|---|---|
| f | 函数 |
| up | 上值序号 |
名字, 值
local secret = '123' local function f() return secret end print(debug.getupvalue(f, 1)) --> secret 123
设置任意对象的环境表(setfenv 的强制版,可作用于线程等)。
| 参数 | 说明 |
|---|---|
| object | 对象 |
| envtable | 环境表 |
该对象
debug.setfenv(loadstring('return x'), {x = 999})设置调试钩子:mask 由 "c"(调用) "r"(返回) "l"(每行) 组成,count 为计数触发间隔。性能开销大,仅调试用。
| 参数 | 说明 |
|---|---|
| thread | 协程,可选 |
| hook | 钩子函数(nil 移除) |
| mask | 触发掩码字符串 |
| count | 计数间隔 |
无
-- 每执行一行打印一次文件与行号 debug.sethook(function() end, 'l') debug.sethook() -- 移除
修改栈上 level 层第 local 个局部变量的值。
| 参数 | 说明 |
|---|---|
| thread | 协程,可选 |
| level | 栈层级 |
| local | 变量序号 |
| value | 新值 |
变量名(失败 nil)
-- debug.setlocal(1, 1, 999) -- 把第一个局部变量改成999
给任意对象(包括数字、字符串、nil 以外的非表值)强制设置元表(绕过 __metatable)。给数字加“默认方法”的经典用法。
| 参数 | 说明 |
|---|---|
| object | 任意对象 |
| table | 元表(nil 移除) |
该对象
-- 给所有数字补一个乘方方法
local nummt = getmetatable(0) or {}
nummt.__index = {pow = function(n, p) return n ^ p end}
debug.setmetatable(0, nummt)
print((2).pow(10)) --> 1024修改函数 f 的第 up 个上值的值。可以热修闭包内部状态(慎用)。
| 参数 | 说明 |
|---|---|
| f | 函数 |
| up | 上值序号 |
| value | 新值 |
上值名字(失败 nil)
-- debug.setupvalue(f, 1, '新密码')
返回当前调用栈的可读描述串(可加 message 前缀)。配合 pcall/xpcall 记录报错堆栈,是排查“哪一行炸了”的第一工具。
| 参数 | 说明 |
|---|---|
| message | 附加信息,可选 |
| level | 从哪层开始,默认 1 |
堆栈描述字符串
local ok, err = xpcall(function()
error('业务异常')
end, debug.traceback)
print(err) -- 带完整文件:行号 堆栈
-- 996 实战: 包住整个业务入口
local ok2, err2 = pcall(MyBigFunction)
if not ok2 then release_print('ERR', err2, debug.traceback()) end