【问题标题】:Why the c++ object destructor not called when luaL_error is called?为什么调用 luaL_error 时不调用 c++ 对象析构函数?
【发布时间】:2014-06-13 18:06:01
【问题描述】:

我有一段这样的代码

class Test
{
public:
    Test() {printf(">>> Test()\n");}
    ~Test() {printf(">>> ~Test()\n");}
}

int myFunc(lua_State *L)
{
    Test t;
    luaL_error(L, "error");
    return 0;
}

我知道当 lua 由 c 编译器编译时,它使用 longjmp 来引发错误。因此,我使用 c++ 编译器编译它,以便它使用 c++ 异常来处理错误,并且即使抛出错误也应该调用析构函数。但我的问题是对象的析构函数没有被调用。

但是,下面的代码是有效的(调用了析构函数)

int myFunc(lua_State *L)
{
    Test t;
    throw(1) // just for testing
    return 0;
}

为什么会这样?我确定 LUAI_THROW 宏被解释为 throw 关键字。

【问题讨论】:

  • 这篇文章缺少关键信息,请更新

标签: c++ lua lua-api


【解决方案1】:

函数 luaL_error() 将调用 exit() 取消程序的整个执行!然后没有调用析构函数,因为 Test t 所在的范围没有结束。您应该使用不同的功能来从错误中恢复。

如何从 lua 中调用错误?我认为您需要使用 lua_cpcall 进行受保护的调用以绕过此退出错误功能!

【讨论】:

  • 是的,myFunc 受 lua_pcall 保护。它是一个暴露给 lua 脚本文件的 api 函数。所以,根本原因不是你上面说的。
  • 你试过包围 luaL_error(L, "error");使用 try/catch 块?
  • 经过您的提醒,我试了一下,luaL_error抛出的错误被try {} catch(...) {}块捕获。并且抛出异常时输出“Microsoft C++ exception: lua_longjmp at memory location 0x003fdc6c..”。
  • 你的析构函数被调用了吗?
  • 是的,但这并不能解决我的问题,因为我想将错误传播到调用 lua_pcall 的位置。
【解决方案2】:

根本原因与visual c++编译器的异常处理方式有关。我使用带有 extern "C" 修饰符的 lua 函数(例如 luaL_error)来防止编译器进行名称修改。并且默认的异常处理模式是 /EHsc 假设 extern "C" 函数不抛出异常。因此,无法捕获异常。解决方法是将 /EHsc 更改为 /EHs。

更多信息请参考http://msdn.microsoft.com/en-us/library/1deeycx5.aspx

【讨论】:

    猜你喜欢
    • 2013-08-08
    • 1970-01-01
    • 2010-10-16
    • 2015-08-21
    • 1970-01-01
    • 1970-01-01
    • 2020-11-05
    相关资源
    最近更新 更多