我们正在研究多台计算机,执行用c / c ++编写的程序并使用lua api,并且每一台计算机都会遇到不同的错误。它通常要么是一个分段错误,它的回溯导致我们调用bu liblua,或者通常在尝试调用nil值时给出,就像它是一个函数一样。
奇怪的是,它可以正常工作,直到我们达到许多状态(不,我们绝对需要多个状态,只有一个是不够的)。它们可能引用相同的文件-again,它可以正常工作,直到打开或不打开多个状态。
以下是他们如何打开,注册和关闭,以防在使用多个状态时出现问题:
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状态作为属性,因此有多个状态。
错误消息表明找不到它应该使用的文件......实际上是这样的,可以在没有任何问题的情况下使用,打开的状态更少。
答案 0 :(得分:2)
您提供的呼叫站点片段没有意义。
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
}
编辑2:在澄清之后,它仍然没有意义。
您的代码包含以下片段:
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从一个状态检索值并将它们推送到另一个状态。协同程序提供了单独状态的一些优点,同时共享一组通用的全局变量。