Печать stacktrace из кода C со встроенным lua
Если я правильно понял, 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);
}
Как распечатать трассировку стека из C после начальной ошибки?
Ответы
Ответ 1
Lua по умолчанию вызовет библиотеку отладки "debug.traceback" при возникновении ошибки.
Нет, не будет. Lua runtime (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;
}
Ответ 2
Ответ от Nicols, приведенный выше, является рабочим примером:
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);
}
}
Ответ 3
Я встретил некоторый вопрос так же, как и вы, и я нашел, что этот способ работает:
luaL_traceback(L, L, NULL, 1);
printf("%s\n", lua_tostring(L, -1));
Так как luaL_traceback
является ровно debug.traceback()
, использующим для печати стека, поэтому я считаю, что это может быть правильным способом, и вы можете прочитать руководство по API luaL_traceback
или просто прочитать исходный код Lua, чтобы выяснить что означает параметры.
Ответ 4
Код mxcl имеет некоторые проблемы:
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;
}