使用嵌入式lua从C代码打印stacktrace

Mat*_*att 19 lua stack-trace traceback lua-api

如果我理解正确,默认情况下Lua会在发生错误时调用调试库"debug.traceback".

但是,当将Lua嵌入到C代码中时,就像这里的示例中所做的那样: 简单的Lua API示例

我们只在堆栈顶部提供错误消息.

if (status) {
    /* If something went wrong, error message is at the top of */
    /* the stack */
    fprintf(stderr, "Couldn't load file: %s\n", lua_tostring(L, -1));

    /* I want to print a stacktrace here. How do I do that? */
    exit(1);
}
Run Code Online (Sandbox Code Playgroud)

初始错误后如何从C打印堆栈跟踪?

Nic*_*las 20

默认情况下,Lua会在发生错误时调用调试库"debug.traceback".

不,它不会.Lua 运行时(lua.exe)会这样做,但Lua库本身不会这样做.如果你想要一个带有Lua错误的调用堆栈,那么你需要生成一个.

Lua中运行时通过执行此操作lua_pcall误差函数.调用错误函数时,堆栈尚未展开,因此您可以在那里获得堆栈跟踪.运行时使用的错误函数是这样的:

static int traceback (lua_State *L) {
  if (!lua_isstring(L, 1))  /* 'message' not a string? */
    return 1;  /* keep it intact */
  lua_getfield(L, LUA_GLOBALSINDEX, "debug");
  if (!lua_istable(L, -1)) {
    lua_pop(L, 1);
    return 1;
  }
  lua_getfield(L, -1, "traceback");
  if (!lua_isfunction(L, -1)) {
    lua_pop(L, 2);
    return 1;
  }
  lua_pushvalue(L, 1);  /* pass error message */
  lua_pushinteger(L, 2);  /* skip this function and traceback */
  lua_call(L, 2, 1);  /* call debug.traceback */
  return 1;
}
Run Code Online (Sandbox Code Playgroud)

  • 谢谢,不是一个完整的答案.但是我查了一下lua.c,它给出了如何实际使用回溯功能的全貌. (2认同)

mxc*_*xcl 10

在这里解决尼科尔的答案是一个有效的例子:

static int traceback(lua_State *L) {
    lua_getfield(L, LUA_GLOBALSINDEX, "debug");
    lua_getfield(L, -1, "traceback");
    lua_pushvalue(L, 1);
    lua_pushinteger(L, 2);
    lua_call(L, 2, 1);
    fprintf(stderr, "%s\n", lua_tostring(L, -1));
    return 1;
}

int main(int argc, char **argv) {
    lua_State *L = lua_open();
    luaL_openlibs(L);    
    lua_pushcfunction(L, traceback);
    int rv = luaL_loadfile(L, "src/main.lua");
    if (rv) {
        fprintf(stderr, "%s\n", lua_tostring(L, -1));
        return rv;
    } else {
        return lua_pcall(L, 0, 0, lua_gettop(L) - 1);
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 很好的答案,**注意**较新的lua版本有`lua_getglobal`所以需要使用`lua_getglobal(L,"debug");` (2认同)

she*_*ock 5

我像你一样遇到了一些问题,我发现这种方式有效:

luaL_traceback(L, L, NULL, 1);
printf("%s\n", lua_tostring(L, -1));
Run Code Online (Sandbox Code Playgroud)

因为luaL_traceback正好debug.traceback()用于打印堆栈,所以我认为这可能是一种正确的方法,你可以阅读API手册,luaL_traceback或者只是阅读Lua的源代码来弄清楚params的含义.