【问题标题】:Lua: How to call error without stack traceLua:如何在没有堆栈跟踪的情况下调用错误
【发布时间】:2013-12-31 02:24:13
【问题描述】:

我正在使用 Lua 来解析用某种语言(我们称之为 L)编写的脚本并创建可以由例如运行的 Lua 代码。 LuaJIT。但是为了简化用户的调试,我想将 Lua/LuaJIT 给出的运行时错误映射到 L 文件中的正确行。我通过 xpcalling 创建的 Lua 代码、翻译错误消息和堆栈跟踪,然后使用此消息调用错误来做到这一点。不幸的是,这给了我两个堆栈跟踪,一个由我创建,一个追溯到调用错误的函数。是否有可能摆脱这个堆栈跟踪,或者有更好的方法吗?

local status, err = xpcall(loadedCode, debug.traceback)
if not status then
  error(createANewErrorMessageWithPrettyTraceback(err),0)
end

输出:

luajit: ./my/file.name:5: Some error message
stack traceback:
    my pretty traceback
stack traceback:
    [C]: in function 'error'
    ./my/file/calling/error.lua:44: in function <./my/file/calling/error.lua:26>
    ./my-main:16: in main chunk
    [C]: at 0x00404180

我知道,例如Moonscript 做了类似的事情,但据我所知,他们只是将新的错误消息写入 stderr,然后照常继续,而不是停止我想要做的程序。
有可能这样做然后不带参数调用错误,这会使程序失败(实际上我认为失败是错误),但这感觉是一个非常丑陋的解决方案,所以我宁愿保留愚蠢的第二次跟踪比那样做。
PS:我假设标题所要求的实际上不起作用(因为错误只需要两个参数),所以我实际上要问的是如何实现这样的事情。 (是否还有其他功能可以做类似的事情,或者我应该在哪里弄清楚如何自己编写该功能。)
编辑:是否可以编辑错误用于获取其回溯的函数,就像使用 debug.traceback 一样?

【问题讨论】:

  • 为什么不直接打印回溯而不是调用错误?
  • 因为我希望程序在出现错误时失败,而不是仅仅告诉用户发生了什么事。但正如 Ryan Stein 在下面指出的,我可以调用 os.exit。

标签: lua


【解决方案1】:

我想做类似的事情(仅直接来自 Lua),我最终覆盖了 debug.traceback 函数本身以更改堆栈跟踪以满足我的需要。我的代码如下;看看这个方法是否也适合你:

  local dtraceback = debug.traceback
  debug.traceback = function (...)
    if select('#', ...) >= 1 then
      local err, lvl = ...
      if err and type(err) ~= 'thread' then
        local trace = dtraceback(err, (lvl or 2)+1)
        if genv.print == iobase.print then -- no remote redirect
          return trace
        else
          genv.print(trace) -- report the error remotely
          return -- don't report locally to avoid double reporting
        end
      end
    end
    -- direct call to debug.traceback: return the original.
    -- debug.traceback(nil, level) doesn't work in Lua 5.1
    -- (http://lua-users.org/lists/lua-l/2011-06/msg00574.html), so
    -- simply remove first frame from the stack trace
    return (dtraceback(...):gsub("(stack traceback:\n)[^\n]*\n", "%1"))
  end

【讨论】:

    【解决方案2】:

    您可以简单地显示您想要的修改后的回溯并退出。

    local function errh(err)
        print(createANewErrorMessageWithPrettyTraceback(debug.traceback(err, 2)))
        os.exit(-1) -- error code
    end
    
    local status, result = xpcall(loadedCode, errh)
    -- The script will never reach this point if there is an error.
    print(result)
    

    【讨论】:

      猜你喜欢
      • 2013-08-03
      • 1970-01-01
      • 1970-01-01
      • 2016-05-12
      • 2011-02-05
      • 2019-09-09
      • 2010-11-07
      • 1970-01-01
      • 2018-08-20
      相关资源
      最近更新 更多