Il C++ standard afferma quanto segue riguardo l'esecuzione di std::call_once
con funzioni che gettano eccezioni (§30.4.4.2/2):un'eccezione da std :: call_once
2/Effetti: Un'esecuzione di call_once ciò non chiama la sua funzione è un'esecuzione passiva. Un'esecuzione di call_once che chiama la sua funzione è un'esecuzione attiva. Un'esecuzione attiva deve chiamare INVOKE (DECAY_- COPY (std :: forward (func)), DECAY_COPY (std :: forward (args)) ...). Se tale chiamata a func genera un'eccezione, l'esecuzione è eccezionale, altrimenti viene restituita. Un'eccezionale esecuzione deve propagare l'eccezione al chiamante di call_once. Tra tutte le esecuzioni di call_once per ogni dato once_flag: al massimo una sarà un'esecuzione di ritorno; se c'è un'esecuzione di ritorno, deve essere l'ultima esecuzione attiva; e ci sono esecuzioni passive solo se c'è un'esecuzione di ritorno. [Nota: le esecuzioni passive consentono ad altri thread di osservare in modo affidabile i risultati prodotti dall'esecuzione di ritorno precedente. - nota end]
Sto utilizzando Visual Studio 2012 e l'esecuzione del seguente codice:
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;
}
Il mio risultato è: il codice viene eseguito blocco catch e stampa il messaggio, ma quando il programma esisto ricevo una chiamata al abort()
e il seguente messaggio stampato a cout:
... \ mutex.c (38) mutex distrutto mentre occupato
È questo dovrebbe succedere?
No, è un bug, il programma dovrebbe funzionare bene (anche se stai usando un costruttore non standard per 'std :: exception', in ISO C++ puoi solo costruire predefinito' std :: exception', che causa frequenti problemi di portabilità quando gli utenti di MSVC controllano l'incodifica che si intende compilare su altre implementazioni) –