2016-06-13 25 views
9

Dai un'occhiata a questo codice che fa terminare il programma senza rilevare l'eccezione.Perché le eccezioni da unique_ptr destructor interrompono il programma?

Questa domanda è diversa dalla domanda di overflow dello stack: throwing exceptions out of destructor.

La differenza è che solo quando si utilizza unique_ptr<test> l'eccezione non viene rilevata.

si può vedere il codice dal vivo, modificare e compilare qui http://cpp.sh/9sk5m

+6

Perché 20.10.1.2.2 richiede che la cancellazione non crei eccezioni. Stai violando le precondizioni della biblioteca. –

+0

Ho una libreria che dipende totalmente da questo, non posso romperla. C'è una soluzione alternativa per questo? Grazie. – amin

+9

Soluzione temporanea: correggi la tua libreria, fallo ora prima [ti morde ulteriormente] (http://stackoverflow.com/a/130123/3426025). – BeyelerStudios

risposta

13

che è richiesto dalla norma. Come da unique.ptr.single.dtor, 20.10.1.2.2.1:

Richiede: The get_deleter espressione() (get()) è ben formato, deve avere un comportamento ben definito, e non devono generare eccezioni. [Nota: l'uso di default_delete richiede che T sia un tipo completo. - end nota]

(sottolineatura mia)

Quindi, in realtà, non importa se si distruttore stessa ha noexcept(false) o meno. E 'vietato lanciare in questo caso - parola finale.

Questo è il caso in generale il caso std:: - tranne quando specificato diversamente. Come per res.on.functions, 17.6.4.8.2.4:

In particolare, gli effetti non sono definite nei seguenti casi: [...] se una funzione di sostituzione o funzione del gestore o funzionamento distruttore uscite tramite un'eccezione, se non specificatamente ammessi in applicabile Comportamento richiesto: paragrafo.

(sottolineatura mia)

Nota: In generale, si può hanno gettando distruttori con noexcept(false). Tuttavia, questo è molto pericoloso, poiché std::terminate verrà chiamato se lo stack si è srotolato a causa di un'eccezione generata. Secondo except.ctor, 15.2.1:

Come controllo passa dal punto in cui viene generata un'eccezione ad un gestore, distruttori vengono richiamati da un processo, specificato in questa sezione, chiamati rimozione dello stack. Se un distruttore direttamente richiamato dallo stack si chiude con un'eccezione, viene chiamato std :: terminate ([except.terminate]). [Nota: Di conseguenza, i distruttori dovrebbero in genere catturare le eccezioni e non lasciarle propagare fuori dal distruttore. - nota end]

(sottolineatura mia)

See it live on Coliru.

+1

Va notato che anche se fornisci * il tuo * distruttore 'noexcept (false)', ciò non cambia il fatto che il distruttore di 'unique_ptr' rimane 'noexcept'. Quindi l'eccezione verrà inghiottita lì. –

+0

"ingerito" implica che scompare. Non è così. – Ven

+0

OK, "esplodere" è probabilmente un termine più accurato di "inghiottire";) Ma in entrambi i casi, non vedrai quell'eccezione raggiungere la tua istruzione 'catch', indipendentemente da quanto tu usi' noexcept (false) ' . –