The C++ Standard states the following about the execution of std::call_once with functions that throw exceptions (§30.4.4.2/2):
2/ Effects: An execution of call_once that does not call its func is a passive execution. An execution of call_once that calls its func is an active execution. An active execution shall call INVOKE (DECAY_- COPY ( std::forward(func)), DECAY_COPY (std::forward(args))...). If such a call to func throws an exception the execution is exceptional, otherwise it is returning. An exceptional execution shall propagate the exception to the caller of call_once. Among all executions of call_once for any given once_flag: at most one shall be a returning execution; if there is a returning execution, it shall be the last active execution; and there are passive executions only if there is a returning execution. [ Note: passive executions allow other threads to reliably observe the results produced by the earlier returning execution. — end note ]
I'm using Visual Studio 2012 and running the following code:
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;
}
My result is: the code in the catch block runs and prints the message, but when the program exists I get a call to abort() and the following message printed to cout: 
...\mutex.c(38) mutex destroyed while busy
Is this supposed to happen?
Is this supposed to happen?
No, not really. This is a bug.
However, notice the fact that VC11 is not alone on this:
std::terminate() as if your exception was not handled (see live example);GCC 4.7.2 and Clang 3.2, on the other hand, behave correctly.
By the way, it is worth noticing that the C++ Standard (Paragraph 18.8.1) specifies that std::exception only has a default constructor and a copy constructor. The constructor you are using is most likely a non-portable MS extension.
You may consider using std::logic_error instead, which derives from std::exception and supports a constructor accepting a string.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With