2015-03-10 18 views
6

Moja duża aplikacja posiada tę strukturę:Jak złapać wyjątki warunkowo?

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

głębi stosu wywołań, różne obiekty sprawdzić ich stan wewnętrzny, rzucając std::runtime_exception jeśli wykryją coś złego. Obsługiwana jest obsługa wyjątków typu all-inclusive, wypisuje niektóre umiarkowanie użyteczne informacje i kończy działanie programu.

Jednak podczas debugowania w MS Visual Studio, mogłem czerpać korzyści z braku obsługi wyjątków: Visual Studio ma swój własny, bardzo przydatny handler, który zatrzymuje moją aplikację w miejscu, w którym wyjątek został zgłoszony, więc Mogę sprawdzić, co poszło nie tak.

Jak mogę zrobić połowu moich wyjątkami warunkowo?

Próbowałem następujące:

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

Dało to dziwny wynik: Visual Studio złapać wyjątek, który został rethrown i pokazał mi ślad stosu w miejscu, gdzie wyjątek. Jednak wszystkie obiekty w mojej aplikacji zostały najwyraźniej zniszczone i nie mogłem zobaczyć np. zmienne lokalne lub członkowskie.

mógłbym zrobić wyjątek obsługi uwarunkowane flagi kompilacji:

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

ale to jest niewygodne, bo muszę skompilować wszystko, jeśli chcę go debugowania.

Tak, jak mogę uczynić wyjątek obsługi moja warunkowy (w zależności od argumentu wiersza poleceń, na przykład)?

+7

Spróbuj 'Debug' ->' Exceptions' i zaznaczyć pole „Przerwa na rzut” za wyjątkiem (ów), które chcesz łapać. – CompuChip

+2

Lepszą metodą byłoby * warunkowo * rzucić wyjątek, którego twoi trenerzy po prostu nie mogą złapać (przez poziom pośredni), pozostawiając go do debuggera, by je porwać. –

+0

Jeśli metoda @ CompuChip działa dla Ciebie, zdecydowanie lepiej z tych dwóch. – TonyK

Odpowiedz

0

Jak sugeruje CompuChip, Visual Studio może złamać wykonanie podczas rzucania wyjątku, nie tylko przy chwytaniu nieprzytomnego!

Aby włączyć to (Visual Studio 2012):

  1. W menu, przejdź Debug -> Wyjątki
  2. W otwartym oknie, zaznacz "rzucony" okno wyjątki wszystko C++ (zaznaczając tylko std::exception nie wystarczy - nie wiem dlaczego)
  3. uruchomić program
0

Jak można ustawić warunkowość mojego wyjątku (w zależności od argumentu wiersza poleceń)?

Pisząc kod do niego: o]

Rozważmy ten oryginalny kod:

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; 
    } 
} 

nowy kod:

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); 
}