从堆栈中读取索引0时出现奇怪的结果

通常 Lua 的栈从索引 1 开始。然而,在调用 cfunction 时提供的 0 号堆栈地址中,我注意到了一个奇怪的现象。

-- 由 Lua C API 定义的 Lua 表
h{ }
u{ }
f{ u{ s{} } }
-- 表调用
h(2)
u(3)
f.u.s(4)

上面看到的所有表(hu和嵌套的s)都有一个指向相同 cfunction 的 __call 元方法。从该 cfunction 中,我正在读取和转储传递的栈:

while(start_index <= lua_gettop(state)) {
    switch(lua_type(state, start_index)) {
        case LUA_TNUMBER:
            std::cout << "LUA_TNUMBER:"<<lua_tonumber(state, start_index);
            break;
        //... dump for all the other types

start_index 从 1 开始时,输出如预期: LUA_TABLE LUA_TNUMBER:3; 它包含包含元方法(至少是我认为的)和参数 3 的表。


然而,当 start_index 从 0 开始时,我想象中的结果不是有效的 Lua 类型,但实际上它确实是。结果是不一致的:从 Lua 调用时,索引 0 始终是一个 LUA_TNUMBER,其值为 5

但是当通过 pcall 在 C ++ 中调用时(lua_getfield、lua_pushnumber、lua_pcall),索引 0 对于调用 f.u.s 仍然是相同的 LUA_TNUMBER(5),但是对于 huLUA_TABLE

索引 0 中的内容是什么,为什么它是一个有效的 Lua 类型,为什么它的值如此奇怪不一致?

点赞
用户501459
用户501459

Lua手册中可以得知:0不是一个有效的堆栈索引,所以你不能依赖于在那儿找到任何东西。这有点像拿到lua_State指针并对(lua_State-1)进行解引用,然后询问其中有什么值。这是无用的。

API中任何接收栈索引的函数都仅适用于有效索引或可接受索引。

一个_有效索引_是指引用堆栈内真实位置的索引,即其位置位于1和堆栈顶部之间(1=abs(index)=top)。

一个_可接受的索引_可以是任何_有效的索引_,包括伪索引,但它也可以是堆栈顶部之后的任何正索引,即堆栈大小内的索引。

(请注意,0永远不是可接受的索引)

通过查看源代码(参见index2addr),如果Lua是使用LUA_USE_APICHECK构建的,你的调用将会抛出一个错误。

2014-05-02 19:29:00