穿过try块使用longjmp安全吗?

我有以下的lua_CFunction,是用C++编写的:

int my_function(lua_State* L) {
    int x = 0;
    try {
        x = do_cpp_stuff_that_invokes_lua_API_as_well();
    } catch(const std::exception& ex) {
        lua_pushstring(ex.what().c_str());
        lua_error(L);
    }
    return x;
}

我的问题是:在以下情况中调用可能会longjmp的lua_error(L)或调用任何可能会longjmp的lua函数是否可以:

  • 在try块内?
  • 在catch块内?

我只需要注意通过不分配依赖于析构函数的任何内容(字符串等)来分配在堆栈上的变量即可。如果我需要这样做,那么在该范围内的所有lua函数都被包装在pcall中,如果pcall失败,则向此函数抛出异常。 简而言之,我关心的是try-catch块。

非常感谢。

点赞
用户2756719
用户2756719

相关规则是(§18.10 [support.runtime]/p4):

在这个国际标准中,函数签名 longjmp(jmp_buf jbuf, int val) 的行为受到更严格的限制。如果将setjmplongjmp替换为catchthrow会调用任何自动对象的非平凡析构函数,则setjmp/longjmp调用对的行为是未定义的。

C++ 标准没有限制 setjmplongjmp 的使用。

2014-09-08 12:23:47
用户1991979
用户1991979

如果您从catch块中进行长跳转,那么至少会泄漏用于存储异常对象的内存。编译器会生成释放此内存的代码,在跳出catch块的控制流路径上。如果进行长跳转,则不会采取这些路径之一。

Sun Studio 的文档 明确禁止混合使用异常和 longjmp:

特别地,您不能直接或间接地 longjmp 进入或退出 try-block 或 catch-block,或 longjmp 长达自动变量或临时变量的初始化或非平凡销毁。

2015-04-13 15:50:34