CHUAN2 DEV ENGINE
996 正版授权研发中心 · 360 授权合作教学中心 · 抖音传奇直播合作授权 · 快手推广运营商授权
OFFICIAL LICENSED ACADEMY 查验官方授权证书 →
// 威海旷世互娱教学基地 · 技术文章
调试热更Lua进阶

【调试实战】debug 库与错误栈回溯还原

2026-09-20 07:41 作者:996 技术组 2 阅读 996引擎Lua教程传奇脚本
完整课程入口:996 全套课程体系Lua 学习路径幂尔框架 mirs.cn

出错不可怕,查不到位置才可怕

线上脚本出了 bug,最贵的不是修复成本,而是"不知道哪一行错的"。Lua 的 debug 库就是为这件事准备的:它能在运行时拿到调用栈、函数信息、甚至局部变量的值。996 引擎的 Lua 报错默认会打一行错误消息,但业务复杂之后,你需要自己把完整的栈带回来看。

最常用的组合是 xpcall + debug.traceback:普通 pcall 只返回"失败了"和一句错误字符串,而 xpcall 的第二个参数是错误处理器,在错误发生的瞬间被调用,此时 debug.traceback 能拿到完整调用链:

lua
local function mainLogic()
    local t = nil
    return t.field   -- 这里会炸
end

local ok, err = xpcall(mainLogic, function(e)
    return e .. "\n" .. debug.traceback("stack:", 2)
end)
if not ok then
    release_print("LUA ERROR:\n" .. err)
    -- 这里可以把 err 上报到日志文件或 GM 频道
end

traceback 之外的三把刀

debug.getinfo 能查任意函数的元信息:定义在哪个文件、第几行、有几个 upvalue。排查"这个函数到底被谁改过"时特别有用——热更冲突经常表现为同名函数来源不明,debug.getinfo(f, "S").source 一打印就现形。

debug.getlocal / setlocal 在错误处理器里可以枚举出错那一帧的局部变量名和值。配合上面的 traceback,等于案发现场的物证清单:玩家 id 是多少、参数传成了什么,一目了然。

debug.sethook 可以设置调用钩子,在每行/每次函数调用时触发回调。它是性能剖析器和沙盒限制器的基础:统计每个函数被命中的次数就能找出热点函数;给钩子里加执行计数,超限就 error 掉,可以兜住第三方脚本的死循环。

建一套最小错误上报

把这套东西封装成全站统一的 SafeCall(函数, ...):内部 xpcall + traceback + 把错误串按"时间 + 玩家名 + 栈"写入日志文件,关键业务(充值回调、装备操作)全部走它。上线后每次玩家反馈异常,先翻日志再动手,定位速度完全不同。

两个注意点:debug 库本身有性能开销,traceback 只在错误路径上调用,不要放进高频循环;另外线上环境慎用 sethook 的"每行"模式,钩子触发太密集会拖慢整个 M2,做剖析时临时开、采完样立刻移除。

← 返回文章地图返回研学路径