c - Lua C API : Too many lua_states lead to errors?

标签 c api lua segmentation-fault

我们在多台计算机上工作,执行一个用 c/c++ 编码并使用 lua api 的程序,每台计算机都因不同的错误而崩溃。它通常要么是段错误,其回溯将我们引向 bu liblua 调用,要么是通常在尝试调用 nil 值时给出的错误,就好像它是一个函数一样。

奇怪的是,在我们达到多个状态之前它工作正常(不,我们绝对需要多个状态,只有一个是不够的)。他们可能会引用同一个文件 - 再次,它可以正常工作,直到打开的状态数量少于 - 或者不打开。

以下是它们的打开、注册和关闭方式,以防在使用多个状态时出现问题:

lua_State *state=lua_open();
luaL_openlibs(state)
luaL_loadfile(filename.c_str());
...
lua_register(state,"function",function); //dozens of them
...
lua_close(state);

在完成所有寄存器之前不会创建其他状态,是否关闭取决于使用状态的位置。

这是我在段错误期间得到的结果:

#0  0x0013fe79 in ?? () from /usr/lib/liblua5.1.so.0
#1  0x0013325b in lua_pushlstring () from /usr/lib/liblua5.1.so.0
#2  0x001442ba in ?? () from /usr/lib/liblua5.1.so.0
#3  0x00144b61 in luaL_pushresult () from /usr/lib/liblua5.1.so.0
#4  0x00144de5 in luaL_gsub () from /usr/lib/liblua5.1.so.0
#5  0x0014fb52 in ?? () from /usr/lib/liblua5.1.so.0
#6  0x0014ffb7 in ?? () from /usr/lib/liblua5.1.so.0
#7  0x0013839a in ?? () from /usr/lib/liblua5.1.so.0
#8  0x00138834 in ?? () from /usr/lib/liblua5.1.so.0
#9  0x001337a5 in lua_call () from /usr/lib/liblua5.1.so.0
#10 0x0014f3ea in ?? () from /usr/lib/liblua5.1.so.0
#11 0x0013839a in ?? () from /usr/lib/liblua5.1.so.0
#12 0x00138834 in ?? () from /usr/lib/liblua5.1.so.0
#13 0x00133761 in ?? () from /usr/lib/liblua5.1.so.0
#14 0x00137ea3 in ?? () from /usr/lib/liblua5.1.so.0
#15 0x00137f05 in ?? () from /usr/lib/liblua5.1.so.0
#16 0x00133588 in lua_pcall () from /usr/lib/liblua5.1.so.0

相关代码:

lua_getglobal(L,"require");
lua_pushstring(L,"function");
if(!lua_pcall(L,1,0,0))
{
 ...

作为函数给出的字符串并没有错,它在打开的状态数较少的情况下工作正常。

当它输出“nil value”错误时,这意味着我们没有在程序内部使用相关的 lua_register 调用,但对于所有其他状态都是一样的,它们可以正常工作。

我认为这可能是由于内存泄漏,我真的不明白为什么,因为所有状态都已关闭。

这是否与 lua api 本身有关(比如可能一次打开预定数量的状态,也许)?我知道我没有提供太多细节,但这几乎是与 lua 相关的所有代码。

编辑: 我忘记包含“require”语句(我称之为推送模块),但它已经在代码中(因此,这不是它不起作用的原因),对此感到抱歉。

程序是单线程的。一些对象将 lua 状态作为其属性,因此具有多个状态。

错误消息表明它找不到它应该使用的文件...实际上它已经存在,可以在打开较少状态的情况下毫无问题地使用。

最佳答案

您提供的调用站点片段没有意义。你有

lua_pushstring(L,"function");
if(!lua_pcall(L,1,0,0)) 
{
 ...

它没有显示对名为“function”的函数的检索,而是对堆栈顶部的任何内容的调用,其第一个参数作为字符串 "function" 给出。 .

你的意思是

lua_getglobal(L,"function");
if(!lua_pcall(L,0,0,0)) 
{
 ... // succcess
} else {
    // examine the error from the call for useful information
    fprintf(stderr, "lua_pcall: %s\n", lua_tostring(L,1));
}

编辑: lua_pcall() 返回的错误字符串可能会提供信息。如需更多信息,请将合适的错误函数也放入堆栈,并将其索引作为第 4 个参数传递给 lua_pcall。 .一个不错的选择是 debug.traceback .

void callback(lua_State *L, const char *fname) 
{
    int status
    lua_getglobal(L,"debug");       // put debug.traceback on the stack
    lua_getfield(L,-1,"traceback");
    lua_remove(L,-2);       
    lua_getglobal(L,fname);    // put function on the stack
    status = lua_pcall(L,0,0,-2)
    if (!status)        // call it with no parameters and no return values
    {
        // succcess
    } else {
        // examine the error from the call for useful information
        fprintf(stderr, "lua_pcall returned %d: %s\n", status, lua_tostring(L,1));
        lua_pop(L,1);               // remove error message from the stack
    }
    lua_pop(L,1);                   // remove debug.traceback from the stack
}

Edit2:经过你的澄清,还是没有意义。

您的代码包含以下片段:

lua_register(state,"function",function); //dozens of them
...

以后

lua_getglobal(L,"require");
lua_pushstring(L,"function");
if(!lua_pcall(L,1,0,0))
{
 ...

第一个片段创建了一个全局变量,其值是每个 C 函数。您可以使用 get_global() 调用这些函数和 lua_pcall()如我回答的第一部分所述。

第二个片段正在检索名为 require 的全局变量并使用字符串 "function" 调用它作为其唯一的论点。在 Lua 中表示的等价物是 require"function" ,它将在 the usual way 中寻找名为“function”的模块.即使调用require() , 捕获并报告错误消息是个好主意。在这种情况下,它可能会告诉您,在 require 的一长串逐项列出的位置中,没有名为“function”的模块。看着。

但是您编写的任何内容都没有真正调用函数本身。

但这里还有一个更大的问题。尚不完全清楚为什么一开始就需要多个 Lua 状态,尤其是在单线程程序中。 [coroutines][2] 是否可能更合适?

对于多个州,您必须记住每个州都与其他州极为孤立。将值从一种状态移动到另一种状态的唯一方法是使用 C API 从一种状态检索值并将它们推送到另一种状态。协程提供了独立状态的一些优势,同时共享一组通用的全局变量。

关于c - Lua C API : Too many lua_states lead to errors?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3212475/

相关文章:

c - 使用 while 循环时的段错误

javascript - BINANCE API - 如何使用用户数据流获取账户信息

php - 英国 IP 地址查询 API

c# - 如何将 int 转换为字节数组然后再转换回来?

c++ - 函数调用作为 C 宏的参数

c - 最里面的括号是在 C 中首先计算的吗?

c - 当C中没有左侧时,&&运算符会做什么?

android - 如何保护从 Android 设备到亚马逊服务的 API 调用的 key

Lua 表作为 redis 参数

iterator - 为什么Lua的迭代器是三元组?