Print stacktrace from C code with embedded lua

夙愿已清 提交于 2019-11-30 08:13:38
Nicol Bolas

Lua by default will call the debug library "debug.traceback" when an error occurs.

No, it won't. The Lua runtime (lua.exe) will do that, but the Lua library will not do that on its own. If you want a call-stack with your Lua errors, then you need to generate one.

The Lua runtime does this by using lua_pcall's error function. The stack has not been unwound when the error function is called, so you can get a stack trace there. The error function the runtime uses is this one:

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;
}

Working off Nicol’s answer above here is a working example:

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);
    }
}

I met the some question as you do,and I found this way work:

luaL_traceback(L, L, NULL, 1);
printf("%s\n", lua_tostring(L, -1));

SinceluaL_tracebackis exactlydebug.traceback() using to print the stack,so I think this may be a proper way,and you can read the API manual aboutluaL_traceback or just read the source code of Lua to figure out the what the params means.

mxcl's code has some problem:

static int traceback(lua_State *L) {
    lua_getfield(L, LUA_GLOBALSINDEX, "debug");
    lua_getfield(L, -1, "traceback");
    //---------------------------
    lua_pop(L,-2); //to popup the 'debug'
    //---------------------------
    lua_pushvalue(L, 1);
    lua_pushinteger(L, 2);
    lua_call(L, 2, 1);
    fprintf(stderr, "%s\n", lua_tostring(L, -1));
    return 1;
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!