Lua/C++ - 尝试遍历表时 lua_next() 内出现段错误

ale*_*bee 3 c++ lua segmentation-fault

我有以下 C++ 代码:

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

但是,当它运行时,会报告段错误。LLDB停止消息如下。

* 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
Run Code Online (Sandbox Code Playgroud)

Luaos 是可执行文件名称。为了可移植性,我将 Lua 直接编译成可执行文件。

PSC是lua状态的名称。它是我的辅助配置 lua state (与我的主代码 lua state 相对L),这就是这个名称背后的原因。

k3o*_*3oy 5

看来您的代码只是部分正确,我将lua_next详细解释如何使用,甚至您的代码正确执行的部分。
lua_next期望堆栈中至少有两个元素(按以下顺序):

[1] previous key
...
[t] table
Run Code Online (Sandbox Code Playgroud)

在第一次调用该函数时,previous key函数nil会将第一对键值压入堆栈,然后开始遍历。

lua_getglobal(L, "theTable"); // Stack table
// ...
lua_pushnil(L);               // Push nil
lua_next(L, t);               // t is theTable index
Run Code Online (Sandbox Code Playgroud)

调用时lua_next会弹出前一个键并将键值对推送到堆栈,因此它看起来像这样:

[1] value
[2] key
...
[t] -- unknown value --
[t+1] table
Run Code Online (Sandbox Code Playgroud)

如果使用此堆栈再次调用该函数,它将具有value当前键作为输入和 未知值table,因此会发生错误。[1] value避免弹出栈顶 ( )

lua_pop(L, 1); // Pop value
Run Code Online (Sandbox Code Playgroud)

现在堆栈将具有继续遍历的预期值,并且lua_next可以再次调用。当表中不再有元素时,该函数将返回 0。
这是一个完整的示例:

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
}
Run Code Online (Sandbox Code Playgroud)