Lua C api:太多 lua_states 导致错误?
我们在多台计算机上工作,执行用 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 状态作为其属性,因此具有多个状态。
错误消息表明它找不到应该使用的文件...实际上它一次又一次地存在,可以在打开的状态较少的情况下毫无问题地使用。
We're working on multiple computers, executing a program coded in c/c++ and using lua api, and each one of them get crashed with different errors. It's usually either a segmentation fault, whose backtrace leads us to a call made bu liblua, or one that is usually given when trying to call a nil value as if it was a function.
The weird thing is, it works just fine until we reach a number of states (no, we absolutely need multiple states, only one won't be enough). They might refer to the same file -again, which works fine until less than a number of states are opened- or not.
Here's how they're opened, get registered and closed, in case there's something wrong when using multiple states :
lua_State *state=lua_open();
luaL_openlibs(state)
luaL_loadfile(filename.c_str());
...
lua_register(state,"function",function); //dozens of them
...
lua_close(state);
No other state is created until all the registers are done, whether it's closed or not depends on where the state is used.
Here's what I get during the segmentation fault :
#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
And the related code :
lua_getglobal(L,"require");
lua_pushstring(L,"function");
if(!lua_pcall(L,1,0,0))
{
...
The string given as the function isn't wrong, it works fine with less than a number of states opened.
When it outputs the "nil value" error, it implies that we didn't use the related lua_register call from inside the program, but it's the same for all other states and again, they work without any problem whatsoever.
I thought it might be due to some memory leak, which I really don't get why since all states are closed.
Is this related to lua api itself (like having a predeterminded number of states might be opened at a time, maybe) ? I know I didn't give too much details, but this is really almost all of the code that is related to lua.
Edit : I forgot including the "require" statement (which I call to push a module), but it was already in the code (thus, not the reason it doesn't work) , sorry about that.
The program is single-threaded. Some objects have lua states as their attributes, hence, multiple states.
The error message indicates it can't find the file it should use... which is actually there and again, can be used without any problem with less states opened.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您提供的调用站点片段没有意义。其中
不显示对名为“function”的函数的检索,而是对堆栈顶部的任何内容进行调用,其第一个参数以字符串“function”形式给出。
您的意思可能是
编辑:从
lua_pcall()
返回的错误字符串可能会提供信息。要了解更多信息,请将合适的错误函数也放入堆栈中,并将其索引作为第四个参数传递给 lua_pcall。一个不错的选择是debug.traceback
。编辑2:经过你的澄清,它仍然没有意义。
您的代码具有以下片段:
以及稍后
第一个片段创建一个全局变量,其值是每个 C 函数。您可以使用
get_global()
和lua_pcall()
调用这些函数,如我答案的第一部分所述。第二个片段正在检索名为
require
的全局变量,并使用字符串"function"
作为唯一参数来调用它。 Lua 中的等价表达是require"function"
,它将在 通常的方式。即使在调用require()
时,捕获并报告错误消息也是一个好主意。在这种情况下,它可能会告诉您,在require
查找的一长串逐项位置中的任何一个位置中都没有名为“function”的模块。但您编写的任何内容都没有实际调用该函数本身。
但这里还有一个更大的问题。目前尚不完全清楚为什么首先需要多个 Lua 状态,尤其是在单线程程序中。 [协程][2] 是否可能更适合?
对于多个状态,您必须记住每个状态都与其他所有状态都极其隔离。将值从一种状态移动到另一种状态的唯一方法是使用 C API 从一种状态检索值并将其推送到另一种状态。协程提供了单独状态的一些优点,同时共享一组通用的全局变量。
The call-site fragment you give doesn't make sense. You have
Which doesn't show retrieval of the function named "function", but rather a call to whatever was on top of the stack with its first argument given as the string
"function"
.Did you perhaps mean
Edit: The error string returned from
lua_pcall()
is likely to be informative. For even more information, put a suitable error function on the stack as well, and pass its index as the 4th argument tolua_pcall
. A good choice isdebug.traceback
.Edit2: After your clarification, it still doesn't make sense.
Your code has the following fragments:
and later
The first fragment creates a globals whose values are each C function. You would call those functions with
get_global()
andlua_pcall()
as described in the first part of my answer.The second fragment is retrieving the global named
require
and calling it with the string"function"
as its only argument. The equivalent expressed in Lua isrequire"function"
, and it would be looking for a module named "function" in the usual way. Even when callingrequire()
, it is a good idea to catch and report the error message. In this case, it is likely to tell you that there is no module named "function" in any of a long list of itemized places thatrequire
looked.But nothing you've written actually invokes the function itself.
But there is a larger concern here. It isn't entirely clear why you need more than one Lua state in the first place, especially in a single-threaded program. Is it possible that [coroutines][2] are a better fit?
With multiple states, you must remember that each state is extremely isolated from all the others. The only way to move values from one state to another is through using the C API to retrieve values from one state and push them to the other. Coroutines give some of the advantages of separate states, while sharing a common set of globals.