From C, how can I print the contents of the Lua stack?
Asked Answered
H

2

6

My C program probably has a silly bug. There is a certain point where the Lua stack doesn't contain the values that I think it should.

In order to debug it, I want to print the contents of the Lua stack at a certain point of my program. How can I do that without messing up the stack in the process?

Homeless answered 28/11, 2019 at 14:51 Comment(5)
Does this answer your question: Can we get stack trace for lua similar to core dump for C and C++ applications? Or this: Get true stack trace of an error in lua pcall?Polack
Unfortunately not. I already have a stack trace when my program crashes, and I already know what line it is crashing. What I want is to be able to print the Lua values that are being stored in the stack, for the current stack frame. That is, the contents of the slots from 1 to get_top(L)Homeless
I don't see why this was closed as too broad (I voted dupe), so I voted to reopen.Polack
This should not be closed as too broad. The Lua stack is a very specific thing, in the C API for Lua. It is not at all unclear.Sumer
See lua-users.org/lists/lua-l/2017-12/msg00068.htmlChapel
H
12

This answer is a slightly edited version of the answer provided by @lhf in the comments.

It has the advantage that it does not modify any values in the stack, and does not require any additional space.

static void dumpstack (lua_State *L) {
  int top=lua_gettop(L);
  for (int i=1; i <= top; i++) {
    printf("%d\t%s\t", i, luaL_typename(L,i));
    switch (lua_type(L, i)) {
      case LUA_TNUMBER:
        printf("%g\n",lua_tonumber(L,i));
        break;
      case LUA_TSTRING:
        printf("%s\n",lua_tostring(L,i));
        break;
      case LUA_TBOOLEAN:
        printf("%s\n", (lua_toboolean(L, i) ? "true" : "false"));
        break;
      case LUA_TNIL:
        printf("%s\n", "nil");
        break;
      default:
        printf("%p\n",lua_topointer(L,i));
        break;
    }
  }
}

If you want, you can also use lua_isinteger(L, i) inside the LUA_TNUMBER case in order to distinguish between integers and floating-point numbers.

Homeless answered 29/11, 2019 at 2:0 Comment(0)
U
1

This code traverses the stack from top to bottom and calls tostring on every value, printing the result (if no result is obtained, it prints the type name).

assert(lua_checkstack(L, 3));
int top = lua_gettop(L);
int bottom = 1;
lua_getglobal(L, "tostring");
for(int i = top; i >= bottom; i--)
{
    lua_pushvalue(L, -1);
    lua_pushvalue(L, i);
    lua_pcall(L, 1, 1, 0);
    const char *str = lua_tostring(L, -1);
    if (str) {
        printf("%s\n", str);
    }else{
        printf("%s\n", luaL_typename(L, i));
    }
    lua_pop(L, 1);
}
lua_pop(L, 1);
Unity answered 28/11, 2019 at 15:38 Comment(5)
You have forgotten to check the space available in Lua C API stackOskar
Unfortunately, this solution does not preserve the value of L->top so it doesn't work for me.Homeless
@Homeless It does not? When the code ends, it should have the initial value.Unity
A fixed version of this code would have to ensure that there is enough space available to push the extra elements, which might require reallocating the stack. You are right that most of the time this should not matter, but it does mean that if you are trying to debug a crash involving the Lua stack calling thid print function could change the behavior of the program you are trying to debug.Homeless
This code changes the values in the stack: it converts numbers to strings.Chapel

© 2022 - 2024 — McMap. All rights reserved.