Lua 出现崩溃,当 metatable __index 指向函数且返回值未被使用时

我试图使用函数作为 metatable __index 来实现更大的灵活性,但当 Lua 端未将返回值分配给某个变量时,它就会崩溃。

以下是 C++ 的部分代码,它只创建了一个表变量,其中 __index 指向一个 C 函数,该函数仅返回一个固定的数字值:

int meta_index( lua_State* lua )
{
    juce::Logger::writeToLog( "meta_index with key " + juce::String( lua_tostring( lua, 2 ) ) );
    lua_pushnumber( lua, 123.456 );
    return 1;
}

int main()
{
    lua_State* lua = luaL_newstate();
    luaL_openlibs( lua );

    // create a table with __index slot
    lua_createtable( lua, 0, 0 );
    lua_pushstring( lua, "__index" );
    lua_pushcfunction( lua, meta_index );
    lua_settable( lua, -3 );
    lua_setglobal( lua, "test_meta" );

    // run lua code
    luaL_loadstring( lua, lua_src );
    lua_call( lua, 0, 0 );
    lua_close( lua );
}

这是导致崩溃的 Lua 代码:

const char* lua_src =
    "a = {}\n"
    "setmetatable(a, test_meta)\n"
    "a.foo\n";

代码在调用实际的 C 函数 meta_index 之前崩溃,并且显示错误信息 _attempt to call a string value_。

然而,如果我将触发元表索引的表达式 a.foo 放在赋值符号右侧,代码可以完成没有错误并产生预期的结果:

const char* lua_src =
    "a = {}\n"
    "setmetatable(a, test_meta)\n"
    "bar = a.foo\n"
    "print(bar)\n";

似乎 Lua 将 a.foobar = a.foo 中的 foo 视为不同的事物,那么它的实际规则是什么呢?

点赞
用户107090
用户107090

由于 Lua 中 a.foo 这样的表达式不是语句,因此下面的代码无法编译:

a = {}
setmetatable(a, test_meta)
a.foo

错误信息为

4: syntax error near <eof>

luaL_loadstring 函数执行后,该字符串被留在栈顶。因此,当您调用 lua_call 时出现 attempt to call a string value 错误。

底线:始终检查 luaL_loadstring 的返回代码并打印任何错误消息。

2021-06-29 12:15:57