2012-09-04 19 views
16
incrustado

Si entiendo esto correctamente, Lua por defecto llamará a la biblioteca de depuración "debug.traceback" cuando ocurra un error.Imprimir stacktrace desde el código C con lua

Sin embargo, al incrustar Lua en código C al igual que hizo en el ejemplo aquí: Simple Lua API Example

Sólo tenemos disponible el mensaje de error en la parte superior de la pila.

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 se imprime el seguimiento de la pila de C después de que el error inicial?

+2

En Lua 5.2 puede usar luaL_traceback. – lhf

Respuesta

14

Lua por defecto llamará a la biblioteca de depuración "debug.traceback" cuando ocurra un error.

No, no lo hará. El tiempo de ejecución de Lua (lua.exe) hará eso, pero la biblioteca de Lua no lo hará por sí sola. Si quieres una pila de llamadas con tus errores de Lua, entonces necesitas generar una.

El tiempo de ejecución de Lua lo hace mediante la función de error 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 utiliza el tiempo de ejecución es la siguiente:

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

Gracias, realmente no es una respuesta completa. Pero busqué lua.c y eso da una idea completa de cómo usar realmente la función de rastreo. – Matt

+0

Extender esto para caminar la pila C requeriría una gran cantidad de detalles específicos de la plataforma, pero sin duda se puede hacer. Obviamente, funcionaría mejor si hay símbolos disponibles para el ejecutable. [Esta pregunta] (http://stackoverflow.com/questions/105659/how-can-one-grab-a-stack-trace-in-c) proporciona una serie de enfoques para hacer el lado C. Stringifying el resultado y etiquetarlo en el resultado de 'debug.traceback' es entonces un problema directo. – RBerteig

9

Trabajar fuera la respuesta de Nicol por encima de aquí es un ejemplo de trabajo: código

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

Buena respuesta, ** Nota ** las versiones de lua más nuevas tienen 'lua_getglobal', así que necesito usar' lua_getglobal (L, "debug"); ' –

+0

Si esta función me imprime" nulo "atrás, ¿qué estoy haciendo mal? – PaulD

2

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

Sigues equivocado, [lua_pop] (http://www.lua.org/manual/5.1/manual.html#lua_pop) Muestra n elementos de la pila. Debería usar [lua_remove] (http://www.lua.org/manual/5.1/manual.html#lua_remove) – xpol

5

conocí la pregunta un poco como lo hace, y encontré de esta manera el trabajo:

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

Dado que es exactamente debug.traceback() usando para imprimir la pila, entonces creo que esto puede ser una forma correcta, y puede leer el manual de la API sobre luaL_traceback o simplemente leer el código fuente de Lua para descubrir lo que significan los params.

+0

Parece que esta función no existe en Lua 5.1, que es la versión que debo usar. Demasiado. Tampoco tengo la biblioteca de depuración cargada en mi estado Lua ejecutándose en un dispositivo integrado. – Marko