从的std :: call_once的抛出一个异常(Throwing an exception fr

2019-08-17 10:30发布

C ++标准规定有关的执行下面std::call_once与抛出异常(§30.4.4.2/ 2)功能:

2 /效果:不调用其FUNC call_once的的执行是一种被动的执行。 调用它的FUNC call_once的的执行是一个积极的执行。 积极执行将调用invoke(DECAY_COPY(STD ::向前(FUNC)),DECAY_COPY(标准::前进(参数))...)。 如果以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)互斥破坏而忙碌

这是应该发生的?

Answer 1:

这是应该发生的?

不,不是真的。 这是一个错误

但是,请注意一个事实,即VC11并不孤单这个:

  • 英特尔ICC 13.0.1调用std::terminate()就好像你的异常没有被处理(见活生生的例子 );
  • GCC 4.8.0测试版可能有类似的功能,但它不显示任何输出,它只是吞下异常,并默默终止程序(见活生生的例子 )。 [ 更新:此错误似乎并没有在其他enviroments重复性好,很可能是与配置的问题上liveworkspace.org仅 ]

GCC 4.7.2和3.2锵,在另一方面,表现正常。

顺便说一句,这是值得注意的是,C ++标准(第18.8.1)指定std::exception 只有一个默认的构造函数和拷贝构造函数 。 您正在使用的构造是最有可能是不可移植的MS扩展。

您可以考虑使用std::logic_error相反,从派生std::exception ,并支持构造函数接受一个字符串。



文章来源: Throwing an exception from std::call_once