管理状态和错误处理
使用 lua_pcall 执行受保护调用,并在 C 层处理错误。
管理状态和错误处理 是 CoddyKit 上的免费 Lua Academy 课时。 这是第 4 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Lua Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Lua Academy 课程共包含 4 节课。
多个 Lua 状态
您可以在同一进程中运行多个 lua_State 实例。每个实例都完全独立:拥有独立的全局变量和独立的栈,默认不共享内存。
线程状态
lua_newthread(L) 会创建一个共享同一全局环境、但拥有独立栈的子线程(协程)。Lua 协程在 C 中就是这样实现的。
在状态之间共享数据
独立的 Lua 状态之间不能直接传递数据。请将数据序列化为字符串,或使用可通过用户数据访问的 C 端共享内存结构。
受保护调用与原始调用
lua_pcall 会捕获错误(底层使用 setjmp/longjmp)。lua_call 会传播错误并终止程序。在生产环境中请始终使用 lua_pcall。
// Safe:
if (lua_pcall(L, nargs, nresults, 0) != LUA_OK) {
const char *err = lua_tostring(L, -1);
lua_pop(L, 1);
// handle error
}错误对象
Lua 中的错误可以是任意值,而不仅仅是字符串。error({code=404, msg="not found"}) 会将一个表压入栈中作为错误对象。C 代码会在 pcall 失败时从栈中读取它。
紧急处理器
如果错误从 pcall 中逸出(例如,未受保护地调用 C 函数时),Lua 会在终止程序前调用通过 lua_atpanic(L, fn) 设置的紧急处理器。
// C code
lua_atpanic(L, function(lua_State *L) {
fprintf(stderr, "PANIC: %s\n", lua_tostring(L, -1));
exit(1);
return 0;
});错误时恢复栈
lua_pcall 出错后,栈会恢复到调用前的状态(移除函数和参数,并在栈顶加上错误对象)。
清理状态
完成后请始终使用 lua_close(L) 关闭状态。这会触发所有 __gc 终结器,并释放所有已分配的内存。
线程安全
Lua 状态不是线程安全的。绝不要并发地对同一状态调用两个 C API 函数。请为每个 OS 线程使用一个状态,或使用互斥锁串行化访问。
内存分配器
默认情况下,Lua 使用 realloc。请通过 lua_newstate(allocFn, ud) 提供自定义分配器,以进行内存跟踪、设置限制或使用自定义内存池。
使用多个状态进行沙箱隔离
在全新的、相互隔离且未加载标准库的 Lua 状态中运行不受信任的代码。任何崩溃或资源耗尽都只会影响该状态。
错误处理问题
lua_call 和 lua_pcall 有什么区别?
回顾:管理状态与错误
在生产环境中使用 lua_pcall(绝不要使用 lua_call)。设置紧急处理器,以便进行最后手段的恢复。每个线程保持一个状态。使用多个相互隔离的状态实现沙箱。请始终调用 lua_close 进行清理。
常见问题解答
「管理状态和错误处理」课时是免费的吗?
是的 — 「管理状态和错误处理」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Lua Academy 课程的其余内容,请升级到 CoddyKit PRO。 Lua Academy 课程共包含 4 节课。
「管理状态和错误处理」这节课中我会学到什么?
使用 lua_pcall 执行受保护调用,并在 C 层处理错误。 你通过在浏览器中直接运行的动手代码来练习 Lua Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 Lua Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 Lua Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 4 节课,共 4 节。
「管理状态和错误处理」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 Lua Academy 课中编写并运行代码吗?
能。每节 Lua Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。