从lua_pcall(L, 0, 0, 0)中获取所有错误。

在C/C++中是否可能获取lua堆栈中的所有错误?以下是我尝试的代码:

c++

int main()
{
    lua_State* L = luaL_newstate();
    luaL_openlibs(L);

    if (luaL_loadfile(L, "LuaBridgeScript.lua"))
    {
        throw std::runtime_error("无法找到lua文件");
    }

    int error = lua_pcall(L, 0, 0, 0);
    while (error && lua_gettop(L))
    {
        std::cout << "堆栈大小 = " << lua_gettop(L) << "\n";
        std::cout << "错误 = " << error << "\n";
        std::cout << "错误信息 = " << lua_tostring(L, -1) << "\n";
        lua_pop(L, 1);
        error = lua_pcall(L, 0, 0, 0);
    }
}

lua:

printMessage("hi")
printMessage2("hi2")

输出:

堆栈大小 = 1
错误 = 2
错误信息 = LuaBridgeScript.lua:1: attempt to call global 'printMessage' <a nil value>

我还尝试了即使堆栈大小为0或负数也循环,但我不明白堆栈如何变成负数,程序在几次尝试后崩溃了。

点赞
用户1442917
用户1442917

根据你在评论中澄清的问题,无法报告多个语法错误(只报告第一个错误);因此,在以下片段中,只报告第1行的第一个错误:

if true the --<-- first syntax error 
end 
if false the --<-- second syntax error 
end 

但是,您可以编写自己的解析器(或修改现有的Lua解析器),以便在找到错误后继续处理。例如,您可以查看David Manura的松散解析器的工作方式。

无法报告多个运行时错误(只报告第一个错误);所以在以下片段中,pcall 只会报告第一个错误:

pcall(function()
  nonExistingFunction1() --<-- only this error will be reported
  nonExistingFunction2()
end)
2014-08-13 15:47:56
用户2198692
用户2198692

为了总结我的评论,按照 lua_pcallLua docs , pcall 在代码执行到结尾或者第一个错误时返回。所以在后者情况下,它只会将 一个 消息推入堆栈中。在第一个错误后,它不会继续执行。

你试图实现的是检查文件中是否有可能的错误。在静态类型语言 如 C 中,每个变量必须在编译时定义,因此编译器可以发现调用不存在函数的情况。

然而,Lua 是一种动态类型语言,其中变量没有类型,而是值的占位符(它们确实有类型)。这意味着,在运行时,Lua 无法预先知道 printMessage 是函数、字符串、值还是未定义的(nil)。只有在变量即将被调用时,Lua 才会检查其类型。

因此,不能用这种方式实现你想要的功能。继续运行代码,超过第一个未处理错误是没有意义的,因为该错误可能使得后续的预设无效(比如关于未定义函数应该设置的全局变量的假设) - 这会搞砸一切。

至于语法错误,这些通常在编译源文件时被捕捉到,也就是在加载时。但是,Lua 解析器会在遇到第一个语法错误时停止解析。这是因为许多情况下,一个地方的语法错误会使接下来的所有内容都失效。就像 Etan 在他的评论中指出的一样,很多解析器会报告随后的错误,而这些错误在你修复了先前的错误后会消失或改变。即使是像 MSVS 中那样重量级的解析器也是如此。

2014-08-13 17:47:25