2009-06-04 8 views
15

Ogólnie używam try/catch dla kodu, który ma wiele punktów awarii, dla których niepowodzenia mają wspólną procedurę obsługi.Użycie bloków try/catch w C++

Z mojego doświadczenia wynika, że ​​jest to zazwyczaj kod, który kwalifikuje dane wejściowe lub kontekstowe przed wykonaniem jakiejś czynności lub wyniku po wykonaniu jakiegoś działania.

Otrzymałem porady od literatury i kolegów, aby zminimalizować kod w takich blokach i akceptuję to jako ogólnie dobrą radę.

Chciałbym zrozumieć trochę więcej o fundacji dla wyżej rada:

  • Jaki jest charakter napowietrznych?
  • Czy są najnowsze wytyczne dotyczące rozwoju, które odnoszą się do zalecanego użycia (lub unikania) bloków try/catch?
  • Ile szybciej procesory i nowsze kompilatory zmniejszają problemy z try/catch?

Dzięki z góry za pomoc,

AJ

+0

Nie jestem pewien, czy rozumiem pytanie. Czy martwisz się wydajnością bloków try/catch? Lub pytasz o użycie try/catch do obsługi sprawdzania poprawności danych wejściowych lub czego? – jalf

+0

Dupek z http://stackoverflow.com/questions/43253/measuring-exception-handling-overhead-incc in many other –

Odpowiedz

0

Z mojego doświadczenia największy problem z bloków try/catch jesteśmy często starają się złapać wyjątki zbyt ogólnie. Na przykład, jeśli otworzę moją główną funkcję blokiem try/catch, który przechwytuje (...), zasadniczo próbuję nie pozwolić mojemu programowi na awarię b/c zgłaszanego wyjątku.

Problem z tym podejściem, jak widzę, jest dwojaki. 1) Podczas testowania i debugowania nie widzę żadnych błędów i nie mam możliwości ich naprawienia. 2) To naprawdę rodzaj leniwego wyjścia. Zamiast myśleć o problemach, które mogą pojawić się i zastanawiać się, jakie są ostateczne przypadki, staram się nie zawieść. Próba nie zawieść jest dużo inna niż próba odniesienia sukcesu.

+1

Zawsze możesz złapać i ponownie rzucić. Uwaga: Jeśli wyjątek jest wyłączony z main(), to implementacja jest zdefiniowana, a stos jest rozwijany (więc destruktory mogą nie być wywoływane). W związku z tym zawsze łapię (...) i loguję się z głównym i ponownym rzutem, aby uzyskać komunikat o błędzie systemu Windows. –

5

Na twoje drugie pytanie: ogólne wytyczne są here, Herb Sutter również daje całkiem niezły poradę here.

6

Znalazłem a technical report on C++ performance (ostrzeżenie pdf), które zawiera sekcję o wyjątkach. Może Cię to zainteresować. Miałem współpracowników, którzy wierzyli, że na każdej instrukcji w bloku try/catch kryje się obciążenie, ale ten raport techniczny nie wspiera tego pomysłu.

+0

Ten link przekierowuje teraz do http://www.stroustrup.com/ :( –

+0

@ShawnChin: Tak, znalazłem nowy link, a także zdałem sobie sprawę, że źle zinterpretowałem ten artykuł. Poprawiłem wpis: –

+0

Najnowsza wersja tego raportu jest dostępna tutaj: http://www.open-std.org/jtc1/sc22/wg21/docs/TR18015.pdf –

0

W większości języków wchodzenie i wychodzenie z bloku prób/catch przy użyciu zwykłych metod jest bezpłatne, tylko w przypadku wyjątku funkcja obsługi wyjątku wyszukuje miejsce obsługi wyjątku.

2

Zależy od kompilatora. Dlaczego nie napiszesz prostej funkcji z blokiem try-catch i podobnym bez niego i porównaj wygenerowany kod maszynowy?

17

w C++, koszt zależy od implementacji. Zasadniczo istnieją dwa sposoby implementacji wyjątków:

Pierwszym z nich jest podejście "tabela". Kompilator tworzy zestaw tabel do sprawdzenia w miejscu, w którym wyjątek został zgłoszony, gdzie należy się udać.Kiedy wyjątek jest zgłaszany, musi przeszukiwać każdą tabelę w górę stosu wywołań, aż znajdzie coś, co złapie ten wyjątek. Ponieważ jest to wszystko oparte na czasie wykonywania, wejście lub wyjście z próbnego połowu nie generuje żadnej kary (dobra), ale wyrzucenie wyjątku wiąże się z potencjalnie wieloma badaniami, powodującymi znacznie wolniejszy rzut. Osobiście wolę nie płacić za wypróbowanie bloków catch, ponieważ wyjątki powinny być bardzo rzadką okolicznością. To również zwiększyłoby pliki wykonywalne, gdyby musiały przechowywać tabele.

Sekunda to podejście "kodu". Za każdym razem, gdy kod wchodzi do bloku catch catch, koncepcyjnie położenie bloku jest wypychane na stos. Powoduje to powstanie kosztu podczas wchodzenia i wychodzenia z bloku próbnego catch, jednak gdy zostanie zgłoszony wyjątek, mechanizm wykonawczy może szybko wyskoczyć z stosu, aby znaleźć miejsce, do którego należy się udać. Rzucanie wyjątków jest (dużo?) Szybsze, ale wejście do bloku ma teraz koszt. Umieszczenie próbnego bloku catch w ciasnej pętli niskiego poziomu może spowodować znaczny wzrost.

Powinieneś sprawdzić swój określony kompilator, aby zobaczyć, którego używa.

0

W C++ nie należy używać bloków try/catch do wykonania czyszczenia. Zamiast tego możesz użyć szablonów do akwizycji zasobów.

auto_ptr są jednym [złe] Przykładem

zamki synchronizacji, na których przechowywane mutex jako zmiennej stanu i użyć zmiennej lokalnej (szablony lub regularne zajęcia), aby wykonać .acquire() /. Release() metody.

Im więcej tego dokonasz, tym mniej musisz martwić się ręcznym zwalnianiem obiektów w wyjątkowych warunkach. Kompilator C++ zrobi to za Ciebie.