2012-09-22 14 views
13

Hoy he encontrado un error en un bloque catch:Perder tipo de excepción cuando Regeneración de una excepción de un bloque catch

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

Básicamente si volver a lanzar la excepción eexplícitamente, consigo un nuevo std::exception reconstruido, en De hecho, el mensaje del método what() fue el predeterminado std::string, en lugar de mi mensaje personalizado.

¿Cuál es la explicación? Pensé que throw; es solo una abreviatura de throw ExceptionJustCaught;.

+0

Es la diferencia entre un valor y una referencia. –

+0

Este es un concepto muy importante que a menudo se pasa por alto (y, en mi opinión, un poco complicado de sintaxis que al menos debería ser una advertencia cuando se compila ...). Gran pregunta! – NHDaly

Respuesta

13

Los objetos de excepción son un poco especiales. Están construidos en un lugar especial en la memoria, y su vida está determinada por el bloque de captura en el que están atrapados.

Si dice throw e;, la vida útil de la excepción original termina al final del bloque de captura, y usted está lanzando una nueva excepción copiando e, produciendo así una clásica rebanar problema: Desde e es una referencia polimórfica a un objeto cuyo tipo dinámico es generalmente más derivado que std::exception, termina seccionando la parte derivada del objeto.

Por el contrario, throw; es una declaración especial que reactiva la excepción original, por lo que ya no es capturado, y su vida útil hace no extremo en el extremo del bloque más. De hecho, si captura por referencia no constante, puede seguir modificando el objeto de excepción y volver a lanzar y así comunicar un cambio de estado en los bloques de captura inferiores. ¡Pero tenga en cuenta que volver a lanzar es diferente de lanzar una nueva excepción!

8

Sólo un throw arroja la excepción actual por referencia. throw e copy crea una nueva excepción para lanzar. Esta es la misma manera en que funciona el return.

+0

"por referencia". Exacto, esto no debería perder la implementación correcta de 'what()', que lleva mi mensaje. –

+0

¿Se puede publicar un ejemplo de código completo y compilable con la menor cantidad de líneas posible que demuestren el problema? Lo más probable es que su constructor de copia no conserve el mensaje. –

+0

Las respuestas de Kerrek parecen correctas, sospechaba que había un problema de corte, así que no editaré la pregunta ya que creo que está correctamente respondida. Quizás David tiene razón con otras palabras, pero honestamente no es lo suficientemente claro. –

Cuestiones relacionadas