Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Lua/C++ - Segfault inside lua_next() while trying to walk table

I have the following code in C++:

lua_getglobal(C, "theTable");
lua_pushnil(C);
while (lua_next(C, -2) != 0) {
  /* snip */
}

However, when it runs, a segfault is reported. The LLDB stop message is as follows.

* thread #1: tid = 0x50663f, 0x000000000002b36a luaos`luaH_next + 58, queue =
'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x38)
frame #0: 0x000000000002b36a luaos`luaH_next + 58

Luaos is the executable name. I have Lua compiled directly into the executable, for portability.

P.S. C is the name of the lua state. It is my secondary configuration lua state (as opposed to my primary code lua state L), which is the reason behind the name.

like image 992
alexbuzzbee Avatar asked Mar 03 '26 10:03

alexbuzzbee


1 Answers

It seems that your code is only partially correct, I'm going to explain how to use lua_next in details, even the parts that your code is doing correctly.
lua_next expects at least two elements in stack (in the following order):

[1] previous key
...
[t] table

In the first call to the function previous key should be nil so the function will push the first pair key-value to the stack, and the traversal will begin.

lua_getglobal(L, "theTable"); // Stack table
// ...
lua_pushnil(L);               // Push nil
lua_next(L, t);               // t is theTable index

When called lua_next pops the previous key and pushes a key-value pair to the stack, so it'll look something like this:

[1] value
[2] key
...
[t] -- unknown value --
[t+1] table

If the function is called again with this stack it'll have as inputs value as the current key and an unknown value as the table, thus an error will ocurr. To avoid that the top of the stack ([1] value) should be popped

lua_pop(L, 1); // Pop value

Now the stack will have the expected values for the traversal to continue, and lua_next can be called again. When there are no more elements in the table the function will return 0.
Here is a complete example:

lua_getglobal(L, "theTable"); // Stack table
lua_pushnil(L);               // Push nil
while(lua_next(L, -2) != 0) {
    // Do something with key, value pair
    lua_pop(L, 1); // Pop value
}
like image 81
k3oy Avatar answered Mar 04 '26 22:03

k3oy



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!