2015-03-10 3 views
6

mio grande applicazione ha questa struttura:Come catturare le eccezioni in modo condizionale?

int main() 
{ 
    try { 
     ... 
    } catch (std::exception& e) { 
     std::cout << "Fatal error: " << e.what() << (some more data) << std::endl; 
     return 1; 
    } 
} 

Nel profondo lo stack di chiamate, vari oggetti verificare il loro stato interno, gettando std::runtime_exception se rilevano qualcosa di brutto. Il gestore eccezioni all-inclusive lo cattura, stampa alcune informazioni utili e termina il programma.

Tuttavia, quando eseguo il debug in MS Visual Studio, potrei trarre vantaggio dal non avere alcun gestore di eccezioni: Visual Studio ha il proprio, molto utile gestore, che interrompe la mia applicazione nel punto in cui viene lanciata l'eccezione, quindi Posso esaminare cosa è andato storto.

Come posso eseguire la cattura delle mie eccezioni in modo condizionale?

ho provato la seguente:

try { 
     ... 
    } catch (std::exception& e) { 
     if (IsDebuggerPresent()) 
      throw; 
     else 
      std::cout << "Fatal error: " << e.what() << (some more data) << std::endl; 
    } 

Questo ha dato un risultato strano: Visual Studio catturato l'eccezione che è stato rilanciati e mi ha mostrato la traccia dello stack nel punto in cui è stata generata l'eccezione. Tuttavia, tutti gli oggetti nella mia applicazione sono stati apparentemente distrutti, e non ho potuto vedere ad es. variabili locali o membri.

ho potuto fare il gestore di eccezioni alla condizione che una bandiera compilazione:

#ifdef NDEBUG 
    try { 
#endif 
     ... 
#ifdef NDEBUG 
    } catch (std::exception& e) { 
     std::cout << "Fatal error: " << e.what() << (some more data) << std::endl; 
    } 
#endif 

ma questo è scomodo perché devo ricompilare tutto se voglio eseguire il debug.

Quindi, come posso rendere condizionale la mia gestione delle eccezioni (a seconda di un argomento della riga di comando, ad esempio)?

+7

Try 'debug' ->' Exceptions' e spuntare la casella "break on lancio" per l'eccezione (s) che si desidera catturare. – CompuChip

+2

Un metodo migliore sarebbe quello di * condizionalmente * lanciare un'eccezione che i gestori non possono semplicemente intercettare (attraverso un livello di riferimento indiretto), lasciandola al debugger per strapparli. –

+0

Se il metodo @ CompuChip funziona per te, è sicuramente il meglio di questi due. – TonyK

risposta

0

Come suggerito da CompuChip, Visual Studio può rompere esecuzione quando si lancia un'eccezione, non solo quando si cattura una persona non catturata!

per attivare questa (in Visual Studio 2012):

  1. Nel menu, andare Debug -> Eccezioni
  2. Nella finestra aperta, spuntare la casella "gettato" per tutti C++ eccezioni (ticchettio solo std::exception non è sufficiente - non so perché)
  3. Eseguire il programma
0

Quindi, come posso rendere condizionale la mia gestione delle eccezioni (a seconda di un argomento della riga di comando, ad esempio)?

scrivendo il codice per esso: o]

considerare questo codice originale:

int main() 
{ 
    try { 
     run_the_application(); // this part different than your example 
    } catch (std::exception& e) { 
     std::cout << "Fatal error: " << e.what() << (some more data) << std::endl; 
     return 1; 
    } 
} 

Nuovo codice:

template<typename F> 
int fast_run(F functor) { functor(); return EXIT_SUCCESS; } 

template<typename F> 
int safe_run(F functor) 
{ 
    try { 
     functor(); 
    } catch (std::exception& e) { 
     std::cout << "Fatal error: " << e.what() << (some more data) << std::endl; 
     return EXIT_FAILURE; 
    } 
    return EXIT_SUCCESS; 
} 

template<typename F> 
int run(const std::vector<std::string>& args, F functor) 
{ 
    using namespace std; 
    if(end(args) != find(begin(args), end(args), "/d")) 
     return fast_run(functor); 
    else 
     return safe_run(functor); 
} 

int main(int argc, char** argv) 
{ 
    const std::vector<std::string> args{ argv, argv + argc }; 
    return run(args, run_the_application); 
}