从std::call_once抛出异常
Throwing an exception from std::call_once
c++标准对抛出异常(§30.4.4.2/2)的函数std::call_once
的执行作了如下规定:
2/Effects: call_once的执行如果不调用它的函数是被动执行。调用call_once函数的执行是活动执行。主动执行应该调用INVOKE (DECAY_- COPY (std::forward(func)), DECAY_COPY (std::forward(args))…)。如果调用func抛出异常,则执行异常,否则返回。异常执行应将异常传播给call_once的调用者。对于给定的once_flag,在所有call_once的执行中,最多只能有一次返回执行;退回执行的,为最后一次主动执行;只有在有返回执行的情况下才会有被动执行。[注:被动执行允许其他线程可靠地观察早期返回执行产生的结果。]
我正在使用Visual Studio 2012并运行以下代码:
void f(){
throw std::exception( "Catch me!" );
}
int main( int argc, char* argv[] ){
once_flag flag;
try{
call_once( flag, f );
} catch( const std::exception& e ){
cout << e.what() << endl;
}
return 0;
}
我的结果是:catch块中的代码运行并打印消息,但是当程序存在时,我得到对abort()
的调用,并将以下消息打印到cout:
…mutex.c(38)互斥锁在繁忙时被破坏
这应该发生吗?
这应该发生吗?
不,不完全是。这是一个错误。
但是,请注意,VC11并不是唯一这样做的:
- Intel ICC 13.0.1调用
std::terminate()
,如果你的异常没有处理(见实际例子); - GCC 4.8.0 beta可能做了类似的事情,但它不显示任何输出,它只是吞下异常并静默地终止程序(参见实际示例)。[更新:此错误似乎不能在其他环境中重现,很可能是liveworkspace.org上的配置问题]
顺便说一下,值得注意的是c++标准(第18.8.1段)规定std::exception
只有一个默认构造函数和一个复制构造函数。你正在使用的构造函数很可能是一个不可移植的MS扩展。
您可以考虑使用std::logic_error
,它派生自std::exception
,并支持接受字符串的构造函数。
相关文章:
- 从构造函数抛出异常时如何克服内存泄漏
- 函数如何通知用户它基于函数原型抛出异常?
- 在缺少函数重载时抛出异常,并带有 std::variant 而不是编译时错误
- VisualStudios 会抛出异常,而代码块不会 [C++]
- 如果不包含 pthread,为什么 GCC 的线程标准库实现会抛出异常?
- ZMQ::send() 抛出异常并终止 QNX 进程.为什么以及如何从中恢复?
- new(std::nothrow) int[n] 抛出异常
- 为什么g_object_set抛出异常(vcruntime140.dll)?
- 你能防止 std::regex 在无效表达式上抛出异常吗?
- C++子线程抛出异常
- 我们应该在抛出异常之前取消分配内存吗
- 有没有一种方法可以让OpenCLC++绑定为所有错误抛出异常
- 为什么访问模板化变体作为返回值抛出异常
- 如何实现,错误分配中止而不是抛出异常
- std::p riority_queue::p op什么时候会抛出异常
- 在0x5914F3BE抛出异常(基于.dll)
- std::vector 默认构造函数可以抛出异常吗?
- 挂钩创建文件抛出异常:读取访问冲突
- getaddrinfo 抛出异常
- 如果文件为c ,如何抛出异常