如何使用 lua_checkstack ?

我有一点困惑 lua_checkstack 应该如何使用。

文档说:

int lua_checkstack (lua_State *L, int extra);

确保栈中有 extra 个空闲的栈槽。如果无法将堆栈增加到该大小,则返回 false。此函数永远不会收缩堆栈;如果堆栈已大于新大小,则保持不变。

在 3.2 栈大小 中说:

当您与 Lua API 交互时,您负责确保一致性。特别是,您负责控制堆栈溢出。您可以使用函数 lua_checkstack 来增加堆栈大小。

每次 Lua 调用 C 时,它都会确保至少有 LUA_MINSTACK 个堆栈位置可用。LUA_MINSTACK 被定义为 20,因此通常您不必担心堆栈空间,除非您的代码对堆栈推送元素有循环。

您唯一可以使用堆栈上的其他槽的方法是从 C API 调用某些函数(例如 lua_pushnumberlua_pushstring)- 对吗?

那些函数根据需要增加堆栈大小:

例如这里是 lua_pushnumber 定义:

LUA_API void lua_pushnumber(lua_State *L, lua_Number n)
{
  setnumV(L->top, n);
  if (LJ_UNLIKELY(tvisnan(L->top)))
    setnanV(L->top);  /* Canonicalize injected NaNs. */
  incr_top(L); // <---- HERE
}

这是 incr_top 的定义:

#define incr_top(L) \
  (++L->top >= tvref(L->maxstack) && (lj_state_growstack1(L), 0))

我认为这意味着如果您将堆栈推到堆栈大小之外,它将根据需要增长到 LUA_MAXSTACK,并在堆栈溢出时优雅地失败。lj_state_growstacklua_checkstack 调用的函数。那我为什么还要调用 lua_checkstack

点赞
用户1131467
用户1131467

混乱的原因是:

  1. LuaJIT会根据需要自动增长堆栈(最多LUA_MAXSTACK)。
  2. (原始的)Lua参考实现不会(在不调用lua_checkstack的情况下在LUA_MINSTACK下崩溃或产生未定义的行为)

而手册描述的是第2种情况。

2020-08-06 07:19:26