【问题标题】:Safely reading string from Lua stack从 Lua 堆栈中安全地读取字符串
【发布时间】:2013-03-21 09:51:18
【问题描述】:

如何安全地从 Lua 堆栈中读取字符串值? lua_tostringlua_tolstring 函数都可以引发 Lua 错误(longjmp / 奇怪类型的异常)。因此,应该使用lua_pcall 在保护模式下调用这些函数。但我无法找到一个很好的解决方案如何做到这一点并将字符串值从 Lua 堆栈获取到 C++。真的需要在保护模式下使用lua_pcall调用lua_tolstring吗?

其实用lua_pcall好像不好,因为我想从Lua栈中读取的字符串是lua_pcall存储的错误信息。

【问题讨论】:

    标签: c++ lua


    【解决方案1】:

    lua_tostring之前使用lua_type:如果lua_type返回LUA_TSTRING,那么您可以安全地调用lua_tostring来获取字符串,并且不会分配内存。

    lua_tostring 仅在需要将数字转换为字符串时才分配内存。

    【讨论】:

    • 在不必进行数字到字符串转换的情况下,是否保证 lua_tostring 为“nothrow”?
    • 谢谢,可惜 Lua 参考手册中没有此信息。
    【解决方案2】:

    好的,当你调用 lua_pcall 失败时,它会返回一个错误码。当你调用 lua_pcall 成功时,你会得到零。所以,首先你应该看到 lua_pcall 返回的值,然后使用 lua_type 获取类型,最后使用 lua_to* 函数获取正确的值。

    int iRet = lua_pcall(L, 0, 0, 0);
    if (iRet)
    {
        const char *pErrorMsg = lua_tostring(L, -1); // error message
        cout<<pErrorMsg<<endl;
        lua_close(L);
        return 0;
    }
    
    int iType = lua_type(L, -1);
    switch (iType)
    {
        //...
        case LUA_TSTRING:
            {
                const char *pValue = lua_tostring(L, -1);
                // ...
            }
    }
    

    就是这样。 祝你好运。

    【讨论】:

      【解决方案3】:

      您可以使用lua_isstring函数检查是否可以将值转换为字符串而不会出错。

      【讨论】:

      • 根据 Lua 参考手册 5.2 lua_isstring 不返回是否可以正确转换,但如果可以转换。仍然可能存在“内存不足”或任何其他未记录的错误。
      • @JurajBlaho 我同意你的看法。 lua_isstring 不够安全。
      【解决方案4】:

      这是在 OpenTibia 服务器中的操作方式:

      std::string LuaState::popString()
      {
          size_t len;
          const char* cstr = lua_tolstring(state, -1, &len);
          std::string str(cstr, len);
          pop();
          return str;
      }
      

      来源:https://github.com/opentibia/server/blob/master/src/lua_manager.cpp

      【讨论】:

      • 我想这取决于上下文。我个人会先尝试调用 lua_isstring。
      猜你喜欢
      • 2013-10-26
      • 1970-01-01
      • 2015-04-11
      • 1970-01-01
      • 1970-01-01
      • 2020-12-04
      • 2014-05-14
      • 2012-09-28
      • 1970-01-01
      相关资源
      最近更新 更多