获取 lua pcall 中的错误真实堆栈信息
2017-8-21 2:55:26
收藏:0
阅读:327
评论:2
对于我的 pcall 语句,我一直在做这样的事情:
local status, err = pcall(fn)
if not status then
print(err)
print(debug.stacktrace())
end
这对于一些基本的东西很好用,但问题是 debug.stacktrace() 返回的是当前的相对堆栈跟踪,而不是错误的堆栈跟踪。如果 fn 中的错误发生在堆栈的第 10 层,那么我就不知道它发生在哪里,只知道这个 pcall 块失败了。我想知道是否有一种方法可以获取 pcall 的堆栈跟踪而不是当前的堆栈跟踪。我尝试过 debug.stacktrace(err),但没有改变任何事情。
点赞
用户805875
基本的问题是(大致上)pcall必须展开栈,以便到达您的错误处理代码。这提供了两种解决问题的明显方法:在展开之前创建堆栈跟踪,或将(潜在的)引发错误的代码移开,以便不必删除堆栈帧。
第一种方法由xpcall处理。它设置了一个错误处理程序,可以在堆栈仍然完整的情况下创建消息。 (请注意,有一些情况下,xpcall不会调用处理程序,因此不适合清理代码!但对于堆栈跟踪,它通常足够好。)
第二个选项(始终有效)是通过将代码移动到不同的协程来保留堆栈。而不是
local ok, r1, r2, etc = pcall( f, ... )
做
local co = coroutine.create( f )
local ok, r1, r2, etc = coroutine.resume( f, ... )
现在堆栈(在co中)仍然被保留,并且可以通过debug.traceback(co)或其他debug函数查询。
如果您想要完整的堆栈跟踪,则需要收集协程内部的堆栈跟踪和外部(当前所在位置)的堆栈跟踪,然后将两者结合在一起,同时丢弃后者的第一行:
local full_tb = debug.traceback( co )
.. debug.traceback( ):sub( 17 ) -- drop 'stack traceback:' line
1在OOMs中不调用处理程序的一种情况是:
g = ("a"):rep( 1024*1024*1024 ) -- a gigabyte of 'a's
-- fail() tries to create a 32GB string – make it larger if that doesn't OOM
fail = load( "return "..("g"):rep( 32, ".." ), "(replicator)" )
-- plain call errors without traceback
fail()
--> not enough memory
-- xpcall does not call the handler either:
xpcall( fail, function(...) print( "handler:", ... ) return ... end, "foo" )
--> false not enough memory
-- (for comparison: here, the handler is called)
xpcall( error, function(...) print( "handler:", ... ) return ... end, "foo" )
--> handler: foo
-- false foo
-- coroutine preserves the stack anyway:
do
local co = coroutine.create( fail )
print( "result:", coroutine.resume( fail ) )
print( debug.traceback( co ) .. debug.traceback( ):sub( 17 ) )
end
--> result: false not enough memory
--> stack traceback:
-- [string "(replicator)"]:1: in function 'fail'
-- stdin:4: in main chunk
-- [C]: in ?
2至少在Lua本身不崩溃的情况下。
2017-08-21 04:32:49
评论区的留言会收到邮件通知哦~
推荐文章
- Lua 虚拟机加密load(string.dump(function)) 后执行失败问题如何解决
- 我想创建一个 Nginx 规则,禁止访问
- 如何将两个不同的lua文件合成一个 东西有点长 大佬请耐心看完 我是小白研究几天了都没搞定
- 如何在roblox studio中1:1导入真实世界的地形?
- 求解,lua_resume的第二次调用继续执行协程问题。
- 【上海普陀区】内向猫网络招募【Skynet游戏框架Lua后端程序员】
- SF爱好求教:如何用lua实现游戏内调用数据库函数实现账号密码注册?
- Lua实现网站后台开发
- LUA错误显式返回,社区常见的规约是怎么样的
- lua5.3下载库失败
- 请问如何实现文本框内容和某个网页搜索框内容连接,并把网页输出来的结果反馈到另外一个文本框上
- lua lanes多线程使用
- 一个kv数据库
- openresty 有没有比较轻量的 docker 镜像
- 想问一下,有大佬用过luacurl吗
- 在Lua执行过程中使用Load函数出现问题
- 为什么 neovim 里没有显示一些特殊字符?
- Lua比较两个表的值(不考虑键的顺序)
- 有个lua简单的项目,外包,有意者加微信 liuheng600456详谈,最好在成都
- 如何在 Visual Studio 2022 中运行 Lua 代码?

你需要使用
xpcall函数来提供一个自定义函数,将调用栈信息添加到错误消息中。来自《Lua 程序设计》的内容如下:你可以查看这个 扩展
pcall函数以包含调用栈信息的补丁。如评论中所建议的,你可以在 Lua 5.2+ 或者开启了与 Lua 5.2 兼容性的 LuaJIT 中使用方式为
local ok, res = xpcall(f, debug.traceback, args...),并在 Lua 5.1 中使用上面提到的补丁。