2010-02-18 21 views
9

Aquí está la configuración.¿Qué sucede si utilizo "throw"? sin una excepción para tirar?

Tengo un programa que llama a varias funciones de C++, todos los cuales potencialmente lanzar el mismo conjunto excepción, y quiero el mismo comportamiento de las excepciones en cada función (mensaje de error, por ejemplo impresión & cancelar todos los datos a los valores predeterminados para exceptionA; simplemente imprime para exceptionB; shut-down cleanly para todas las otras excepciones).

Parece como si tuviera que ser capaz de establecer el comportamiento de captura a llamar a una función privada que simplemente relanzamientos el error, y realiza las capturas, así:

void aFunction() 
{ 
    try{ /* do some stuff that might throw */ } 
    catch(...){handle();} 
} 

void bFunction() 
{ 
    try{ /* do some stuff that might throw */ } 
    catch(...){handle();} 
} 

void handle() 
{ 
    try{throw;} 
    catch(anException) 
    { 
     // common code for both aFunction and bFunction 
     // involving the exception they threw 
    } 
    catch(anotherException) 
    { 
     // common code for both aFunction and bFunction 
     // involving the exception they threw 
    } 
    catch(...) 
    { 
     // common code for both aFunction and bFunction 
     // involving the exception they threw 
    } 
} 

Ahora, ¿qué ocurre si "manejar" se llama fuera de la clase de excepción. Soy consciente de que esto nunca debería suceder, pero me pregunto si el comportamiento no está definido por el estándar de C++.

+0

Se termina, pero ¿qué quieres que haga ?, te proporciona un compilador para ejecutar este programa para que puedas verificar el resultado. –

+0

Todo lo que hará un compilador es compilarlo. Y se compilará, porque no hay nada sobre la * definición * de handle para advertir a un usuario que definitivamente requerirá una excepción cargada. Los compiladores no pueden decirle mucho sobre el comportamiento indefinido, especialmente algo como esto que no se recogerá hasta el tiempo de ejecución. – deworde

Respuesta

16

Si llama a handle() fuera del contexto de una excepción, tendrá throw sin que se maneje una excepción. En este caso, el estándar (véase la sección 15.5.1) especifica que

Si actualmente está siendo manejado no es una excepción, la ejecución de un throw-expression sin operandos llama terminate().

por lo que su aplicación finalizará. Probablemente eso no es lo que quieres aquí.

+0

Bueno, no hay una razón lógica para llamar a "handle()" si no estás dentro de un bloque catch, pero me interesaba saber si lo que sucedió se definiría. Esa fue una respuesta perfecta. ¡Gracias! – deworde

5

Si usa lanzar dentro de un bloque catch, volverá a lanzar la excepción. Si usa throw fuera de un bloque catch, terminará la aplicación.

+0

Buena respuesta, aunque la de John fue más clara. ¡Gracias! – deworde

1

Nunca, nunca, nunca use catch (...) ya que podría detectar errores de aplicación que no desea capturar, p. errores, violaciones de acceso (dependiendo de cómo compiló).

Lea el gran libro de John Robbins (Depuración de aplicaciones de Windows) en el que explica con más detalle por qué no debería hacerlo.

+0

http://stackoverflow.com/questions/2183113/using-catch-ellipsis-for-post-mortem-analysis –

+2

Esto es completamente irrelevante para mi pregunta. Además, es inexacto, como se muestra arriba. Hay muchas razones perfectamente buenas para usar (...), siempre que lo maneje correctamente. Por ejemplo, supongamos que quiero liberar un bloqueo en algo que se comparte. Podría esperar hasta que llegue a un destructor, pero es mejor hacerlo tan pronto como esté seguro de que ya no lo necesito. Podría volver a lanzar desde el bloque de captura (...) {} si quería asegurarme de que las violaciones de acceso y los errores todavía provocaran la finalización. – deworde

Cuestiones relacionadas