2012-01-23 9 views
10

Tengo el siguiente código C++ y me da una sorpresa. El problema es que si lanzo algo excepto volver a lanzar dentro del bloque catch, el programa terminará llamando al abortar y aparecerá el mensaje de error en GCC4, "finalizar llamada después de lanzar una instancia de 'int'". Si solo uso "throw"; para volver a tirar dentro del bloque catch, todo estará bien.por qué causa la terminación si trato de lanzar algo dentro de un bloque catch en C++

#include <iostream> 
#include <exception> 
#include <stdexcept> 

using namespace std; 

int main() 
{ 
    try{ 
     throw std::string("first throw"); 
    } 
    catch(std::string &x){ 
     try{ 
      std::cout << x << std::endl; 
//   throw; // if I use this line, all is fine. 
      throw int(2); // but if I use this line, it causes Abort() to be called 
     } 
     catch (int &k){ 
      throw; 
     } 
     catch(...) 
     { 
      cout << "all handled here!"<< endl; 
     } 
    } 
    catch(...){ 
     std::cout<< "never printed" << endl; 
    } 
} 
+0

Si arroja de una captura esto es de esperar. – AJG85

Respuesta

7

Usted throw no está dentro de cualquier manejador try por lo tanto, conduce a abort ser llamado.

Aquí está su código con la sangría limpiado un poco y algunos comentarios en línea:

#include <iostream> 
#include <exception> 
#include <stdexcept> 

using namespace std; 

int main() 
{ 
    try { 
     throw std::string("first throw"); 
    } 
    catch (std::string &x) { 
     try { 
      std::cout << x << std::endl; 
      // throw; // if I use this line, all is fine. 
      throw int(2); // but if I use this line, it causes Abort() to be called 
     } 
     catch (int &k) { 
      // Catches and rethrows exception. Not inside a try thus leads to abort. 
      throw; 
     } 
     catch (...) { 
      // Will handle the case where the string is rethrown instead. No abort. 
      cout << "all handled here!"<< endl; 
     } 
    } 
    catch (...) { 
     std::cout<< "never printed" << endl; 
    } 
} 
+0

Gracias, Martin. ¡Tus comentarios lo hacen más claro para los lectores! –

13

Si se lanza una int, entonces no va a ser manejado; será capturado por el controlador interno catch (int &k), que lo vuelve a lanzar; y no existe un controlador externo para atrapar la excepción retrotraída, ya que ya se encuentra en un bloque externo catch. Entonces, en este caso, se llama al terminate debido a una excepción no controlada.

Si vuelves a lanzar string, es capturado por el controlador interno catch(...); esto no vuelve a ocurrir, por lo que la excepción ha sido manejada.

+0

Gracias, Mike. Creo que tu respuesta es concisa y directa al grano. –

+0

¿Es práctica común/recomendable tirar una cuerda? –

+0

@StephaneRolland: por lo general, no; para informar errores u otras condiciones que no se pueden manejar localmente, genere un tipo personalizado, normalmente una subclase de 'std :: exception'; y para otros fines, probablemente no desee usar excepciones en primer lugar. Pero para aprender cómo funcionan las excepciones, 'string' y' int' son tan buenas como cualquier otra cosa. –

Cuestiones relacionadas