2012-01-23 11 views
10

Ho il seguente codice C++ e mi da una sorpresa. Il problema è che se lancio qualcosa tranne il re-throw all'interno del blocco catch, il programma verrà terminato chiamando abort e darà il messaggio di errore in GCC4, "terminato chiamato dopo aver lanciato un'istanza di 'int'". Se uso solo "lancia"; per rilanciare dentro il blocco catch, tutto andrà bene.perché causa la chiusura se provo a lanciare qualcosa all'interno di un blocco catch in 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

Se si butta fuori da una presa, questo è normale. – AJG85

risposta

7

È throw non è all'interno di qualsiasi try gestore quindi porta a abort essere chiamato.

Qui è il codice con il rientro ripulito un po 'e un po' di commenti in linea:

#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

Grazie, Martin. I tuoi commenti rendono più chiaro ai lettori! –

13

Se si lancia un int, allora non sarà trattati; sarà catturato dal gestore interno catch (int &k), che lo riporterà; e non vi è alcun gestore esterno per catturare l'eccezione di rethrown, poiché si è già in un blocco catch esterno. In questo caso, viene chiamato terminate a causa di un'eccezione non gestita.

Se rigenerare il string, allora è catturato dalla interna catch(...) gestore; questo non si ripete, quindi l'eccezione è stata quindi gestita.

+0

Grazie, Mike. Penso che la tua risposta sia concisa e giusta al punto. –

+0

È pratica comune/consigliata lanciare una corda? –

+0

@StephaneRolland: di solito, no; per segnalare errori o altre condizioni che non possono essere gestiti localmente, lancia un tipo personalizzato, di solito una sottoclasse di 'std :: exception'; e per altri scopi probabilmente non si desidera utilizzare eccezioni in primo luogo. Ma per sapere come funzionano le eccezioni, 'string' e' int' sono buoni come niente. –

Problemi correlati