C ++标准声明了以下关于std::call_once
的执行以及抛出异常的函数(§30.4.4.2/ 2):
2 /效果:不调用其func的call_once的执行是被动执行。调用其func的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)mutex在忙碌时被破坏
这应该发生吗?
答案 0 :(得分:7)
这应该发生吗?
不,不是真的。这是错误。
但是,请注意VC11并不是唯一的事实:
std::terminate()
,就像未处理您的例外一样(请参阅live example); 顺便说一下,值得注意的是C ++标准(第18.8.1段)指定了std::exception
only has a default constructor and a copy constructor。您正在使用的构造函数很可能是非便携式MS扩展。
您可以考虑使用std::logic_error
代替,std::exception
派生自{{1}}并支持接受字符串的构造函数。