2012-09-22 7 views
13

Oggi ho trovato un bug in un blocco catch:Perdere tipo di eccezione quando rethrowing un'eccezione da un blocco catch

catch (const exception& e){ 
    // do something 
    // throw e; <-- bug! 
    throw; // <-- right thing to do 
} 

In pratica se io rigenerare l'eccezione eesplicitamente, ottengo un nuovo std::exception ricostruito, in Infatti il ​​messaggio dal metodo what() era il valore predefinito std::string, anziché il mio messaggio personalizzato.

Qual è la spiegazione? Ho pensato che throw; è solo una stenografia di throw ExceptionJustCaught;.

+0

È la differenza tra un valore e un riferimento. –

+0

Questo è un concetto molto importante che viene spesso trascurato (e, a mio avviso, un po 'complicato di sintassi che dovrebbe essere almeno un avvertimento quando compilato ..). Ottima domanda! – NHDaly

risposta

13

Gli oggetti di eccezione sono un po 'speciali. Sono costruiti in un posto speciale nella memoria e la loro durata è determinata dal blocco di cattura in cui vengono catturati.

Se dici throw e;, la durata del eccezione originale termina alla fine del blocco catch, e si sta gettando una nuova eccezione copiando e, producendo così una classica affettare problema: Dal momento che e è un riferimento polimorfico a un oggetto il cui tipo dinamico è in genere più derivato di std::exception, si finisce per affettare la parte derivata dell'oggetto.

Al contrario, throw; è una dichiarazione speciale che riattiva l'eccezione originale, in modo che non è più catturati, e la sua vita fa non fine alla fine del blocco di più. Infatti, se si cattura per riferimento non costante, è possibile continuare a modificare l'oggetto di eccezione e retrocedere e quindi comunicare uno stato modifica i blocchi di cattura inferiore. Ma ricorda che la riconfigurazione è diversa da una nuova eccezione!

8

Solo un throw genera l'eccezione corrente per riferimento. throw e copy costruisce una nuova eccezione da lanciare. Questo è più o meno allo stesso modo in cui funziona return.

+0

"per riferimento". Esatto, questo non dovrebbe perdere la giusta implementazione di 'what()', che porta il mio messaggio. –

+0

Puoi pubblicare un esempio di codice compilabile completo con il minor numero possibile di righe che mostri il problema? Molto probabilmente, il tuo costruttore di copie non conserva il messaggio. –

+0

Le risposte di Kerrek sembrano corrette, sospettavo che ci fosse un problema di affettamento, quindi non modificherò la domanda perché penso che abbia risposto correttamente. Forse David ha ragione con parole solo diverse, ma onestamente non è abbastanza chiaro. –

Problemi correlati