在catch子句中调用的lambda中是否允许调用std::current_exception()?
Is it allowed to call std::current_exception() in lambda which is called in a catch clause?
我的意思是这样的:
//std::once_flag eptrFlag;
//std::exception_ptr eptr;
//...
try
{
// may throw exceptions
}
catch (...)
{
std::call_once(eptrFlag,
[&]()
{
//...
eptr = std::current_exception();
});
}
这是未定义的行为,还是安全的?
我读过 cppreferences 说:
If called during exception handling (typically, in a catch clause), captures the current exception object
我不确定异常处理期间是什么 除了正常的 catch 子句,catch 块的关闭算作异常处理中?
在 catch
块范围内的任何地方调用 std::current_exception()
是安全的,即使是在嵌套函数调用内部。但是一旦 catch
块退出,它的异常对象就不再有效,除非被 std::current_exception()
.
捕获
首先,调用 std::current_exception
永远不会导致未定义的行为。
至于什么是异常处理,其实语言标准的异常处理也包括处理未捕获的异常(比如C++17标准的18.1(7) );对于 std::current_exception
实际情况是“在活动处理程序处理异常期间”;
异常处理程序在其 catch 子句参数初始化后处于活动状态,直到 catch 子句参数刚刚被销毁。
如果当前未由活动处理程序处理异常,std:current_exception
将 return 一个空的 std::exception_ptr。
调用函数不会中断处理,但活动处理程序处理另一个异常可能会与前一个异常重叠。
至于,在异常处理期间,lambda 函数捕获 catch 块的上下文是否算作 - 在 C++ 中,对于 lambda 函数,这将是 [=38= 的问题]-时间条件,它取决于调用函数的时间,处理程序完成之后或之前;在你的情况下,它总是在之前;如果之后调用,std:current_exception
将 return 一个空的 std::exception_ptr
。
至于这里使用std::call_once
,从这段代码中看不出你到底想要什么,但请注意异常对象和异常处理机制是线程局部的。即使 catch 子句在多个线程中是 运行,它也永远不会处理同一个异常,除非在线程之间传递了对同一个异常对象的引用并且在重新抛出时没有进行复制。
std::current_exception 和 std::rethrow_exception 是否制作副本是实现定义的,如果为不复制的情况编写,你应该只考虑防止同时写入,如果不想让你代码是一个大杂烩,检查它是否被复制,如果没有则处理这种情况(尽管有可能,但没有任何合理的理由)。
我的意思是这样的:
//std::once_flag eptrFlag;
//std::exception_ptr eptr;
//...
try
{
// may throw exceptions
}
catch (...)
{
std::call_once(eptrFlag,
[&]()
{
//...
eptr = std::current_exception();
});
}
这是未定义的行为,还是安全的?
我读过 cppreferences 说:
If called during exception handling (typically, in a catch clause), captures the current exception object
我不确定异常处理期间是什么 除了正常的 catch 子句,catch 块的关闭算作异常处理中?
在 catch
块范围内的任何地方调用 std::current_exception()
是安全的,即使是在嵌套函数调用内部。但是一旦 catch
块退出,它的异常对象就不再有效,除非被 std::current_exception()
.
首先,调用 std::current_exception
永远不会导致未定义的行为。
至于什么是异常处理,其实语言标准的异常处理也包括处理未捕获的异常(比如C++17标准的18.1(7) );对于 std::current_exception
实际情况是“在活动处理程序处理异常期间”;
异常处理程序在其 catch 子句参数初始化后处于活动状态,直到 catch 子句参数刚刚被销毁。
如果当前未由活动处理程序处理异常,std:current_exception
将 return 一个空的 std::exception_ptr。
调用函数不会中断处理,但活动处理程序处理另一个异常可能会与前一个异常重叠。
至于,在异常处理期间,lambda 函数捕获 catch 块的上下文是否算作 - 在 C++ 中,对于 lambda 函数,这将是 [=38= 的问题]-时间条件,它取决于调用函数的时间,处理程序完成之后或之前;在你的情况下,它总是在之前;如果之后调用,std:current_exception
将 return 一个空的 std::exception_ptr
。
至于这里使用std::call_once
,从这段代码中看不出你到底想要什么,但请注意异常对象和异常处理机制是线程局部的。即使 catch 子句在多个线程中是 运行,它也永远不会处理同一个异常,除非在线程之间传递了对同一个异常对象的引用并且在重新抛出时没有进行复制。
std::current_exception 和 std::rethrow_exception 是否制作副本是实现定义的,如果为不复制的情况编写,你应该只考虑防止同时写入,如果不想让你代码是一个大杂烩,检查它是否被复制,如果没有则处理这种情况(尽管有可能,但没有任何合理的理由)。