Imprimir stacktrace desde código C con lua incrustado
stack-trace traceback (4)
Si entiendo esto correctamente, Lua llamará por defecto a la biblioteca de depuración "debug.traceback" cuando ocurra un error.
Sin embargo, al integrar Lua en el código C, como se hace en el ejemplo aquí: Ejemplo de API Lua simple
Solo tenemos disponible el mensaje de error en la parte superior de la pila.
es decir
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);
}
¿Cómo imprimo el seguimiento de pila desde C después del error inicial?
Lua de forma predeterminada llamará a la biblioteca de depuración "debug.traceback" cuando se produzca un error.
No, no lo hará. El tiempo de ejecución de Lua (lua.exe) lo hará, pero la biblioteca de Lua no lo hará por sí sola. Si desea una pila de llamadas con sus errores de Lua, entonces necesita generar uno.
El tiempo de ejecución de Lua hace esto usando lua_pcall''s función de error de lua_pcall''s . La pila no se ha desenrollado cuando se llama a la función de error, por lo que puede obtener un seguimiento de pila allí. La función de error que usa el runtime es esta:
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;
}
El código de mxcl tiene algún problema:
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;
}
Me encontré con algunas preguntas a medida que lo haces, y encontré que esta manera funciona
luaL_traceback(L, L, NULL, 1);
printf("%s/n", lua_tostring(L, -1));
Ya que luaL_traceback
es exactamente debug.traceback()
usando para imprimir la pila, entonces creo que esta puede ser una forma adecuada, y puedes leer el manual de la API sobre luaL_traceback
o simplemente leer el código fuente de Lua para averiguar qué significa el parámetro .
Trabajar con la respuesta de Nicol aquí es un ejemplo de trabajo:
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);
}
}