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