Czy piszesz (naprawdę) bezpieczny kod wyjątku? [zamknięte]

Obsługa wyjątków (EH) wydaje się być aktualnym standardem, a przeszukując Internet, nie mogę znaleźć żadnych nowatorskich pomysłów lub metod, które próbują go poprawić lub zastąpić(cóż, istnieją pewne odmiany, ale nic nowego).

Chociaż większość ludzi zdaje się go ignorować lub po prostu zaakceptować, EH ma kilka ogromnych wad: wyjątki są niewidoczne dla kodu i tworzą wiele, wiele możliwych punktów wyjścia. Joel on software napisał artykuł na ten temat . Porównanie do goto pasuje idealnie, to dało mi do myślenia o EH.

Staram się unikać EH i po prostu używać wartości zwrotnych, wywołań zwrotnych lub cokolwiek pasuje do celu. Ale kiedy musisz napisać niezawodny kod, po prostu nie możesz zignorować EH w dzisiejszych czasach : zaczyna się od new, co może rzucić wyjątek, zamiast po prostu zwracać 0 (jak za dawnych czasów). To sprawia, że każda linia kodu C++ jest podatna na wyjątek. A potem kolejne miejsca w kodzie C++ rzucają wyjątki... std lib does to i tak dalej.

To jest jak chodzenie po chwiejnym terenie .. Więc teraz jesteśmy zmuszeni dbać o wyjątki!

Ale jest ciężko, jest naprawdę ciężko. Musisz nauczyć się pisać bezpieczny kod wyjątku, a nawet jeśli masz z nim jakieś doświadczenie, nadal będziesz musiał dokładnie sprawdzić dowolną pojedynczą linię kodu, aby być bezpiecznym! Albo zaczynasz umieszczać wszędzie bloki try/catch, co zaśmieca kod, aż osiągnie stan nieczytelności.

EH zastąpiła starą czystą podejście deterministyczne(wartości zwrotne..), który miał tylko kilka, ale zrozumiałych i łatwych do rozwiązania wad z podejściem, które tworzy wiele możliwych punktów wyjścia w kodzie, a jeśli zaczniesz pisać kod, który wychwytuje wyjątki (do czego jesteś zmuszony w pewnym momencie), to nawet stworzy wiele ścieżek przez Twój kod (kod w blokach wychwytu, pomyśl o programie serwerowym, w którym potrzebujesz urządzeń rejestrujących innych niż STD:: cerr ..). EH ma zalety, ale to nie jest punkt.

Moje prawdziwe pytania:
  • czy naprawdę piszesz bezpieczny kod WYJĄTKÓW?
  • czy jesteś pewien, że twój ostatni kod "gotowy do produkcji" jest bezpieczny dla WYJĄTKÓW?
  • możesz być w ogóle pewien, że tak jest?
  • Czy wiesz i / lub faktycznie używać alternatyw, które działają?
Author: Frunsi, 2009-12-05

13 answers

Twoje pytanie sprawia, że stwierdzenie, że "pisanie kodu bezpiecznego dla wyjątków jest bardzo trudne". Najpierw odpowiem na twoje pytania, a potem na ukryte za nimi pytanie.

Odpowiadanie na pytania

Czy naprawdę piszesz bezpieczny kod WYJĄTKÓW?

Oczywiście, że tak.

To jest powód, dla którego Java straciła wiele swojej atrakcyjności dla mnie jako programisty C++ (Brak semantyki RAII), ale dygresję: to jest pytanie C++.

It jest, w rzeczywistości, konieczne, gdy trzeba pracować z kodem stl lub Boost. Na przykład, wątki C++ (boost::thread lub std::thread) wyrzucą wyjątek, aby zakończyć z wdziękiem.

Czy jesteś pewien, że twój ostatni kod "gotowy do produkcji" jest bezpieczny dla WYJĄTKÓW?

Czy możesz być w ogóle pewien, że tak jest?

Pisanie kodu bezpiecznego dla wyjątków jest jak pisanie kodu wolnego od błędów.

Nie możesz być w 100% pewien, że Twój kod jest bezpieczny dla WYJĄTKÓW. Ale potem dążysz do tego, używając znanych wzorców i unikanie znanych anty-wzorców.

Czy wiesz i / lub faktycznie używać alternatyw, które działają?

Nie ma realnych alternatyw w C++ (tzn. musisz wrócić do C i uniknąć bibliotek C++, a także zewnętrznych niespodzianek, takich jak Windows SEH).

Zapisywanie bezpiecznego kodu wyjątku

Aby napisać bezpieczny kod wyjątku, musisz najpierw wiedzieć jaki jest poziom bezpieczeństwa wyjątków dla każdej instrukcji, którą piszesz.

Dla na przykład, new może rzucić wyjątek, ale przypisanie wbudowanego (np. int lub wskaźnik) nie zakończy się niepowodzeniem. Swap nigdy nie zawiedzie (nigdy nie pisz swapu rzucającego), a std::list::push_back może rzucać...

Gwarancja wyjątku

Pierwszą rzeczą do zrozumienia jest to, że musisz być w stanie ocenić gwarancję wyjątku oferowaną przez wszystkie twoje funkcje:]}
  1. none : Twój kod nigdy nie powinien tego oferować. Ten kod wycieknie wszystko i zepsuje się na samym początku wyjątek wyrzucony.
  2. To jest gwarancja, którą musisz przynajmniej zaoferować, to znaczy, że jeśli zostanie wyrzucony wyjątek, żadne zasoby nie zostaną wycieknięte, a wszystkie obiekty są nadal w całości.]}
  3. W przeciwieństwie do C++, nie jest w stanie w żaden sposób skompilować danych, ponieważ nie jest w stanie w żaden sposób skompilować danych, które nie zostały w ogóle uruchomione (co daje moc transakcyjną dla C++).]}
  4. nothrow / nofail: przetwarzanie będzie / align = "left" /

Przykład kodu

Poniższy kod wydaje się być poprawnym C++, ale w rzeczywistości daje gwarancję "brak", a zatem nie jest poprawny: {]}
void doSomething(T & t)
{
   if(std::numeric_limits<int>::max() > t.integer)  // 1.   nothrow/nofail
      t.integer += 1 ;                              // 1'.  nothrow/nofail
   X * x = new X() ;                // 2. basic : can throw with new and X constructor
   t.list.push_back(x) ;            // 3. strong : can throw
   x->doSomethingThatCanThrow() ;   // 4. basic : can throw
}
[30]}piszę cały mój kod z myślą o tego rodzaju analizie.

Najniższa oferowana gwarancja jest podstawowa, ale wtedy kolejność każdej instrukcji sprawia, że cała funkcja "brak", bo jeśli 3. rzuca, x przecieka.

Pierwszą rzeczą do zrobienia byłoby uczynienie funkcji "podstawową" , czyli umieszczenie x w inteligentnym wskaźniku, dopóki nie zostanie bezpiecznie własnością listy:

void doSomething(T & t)
{
   if(std::numeric_limits<int>::max() > t.integer)  // 1.   nothrow/nofail
      t.integer += 1 ;                              // 1'.  nothrow/nofail
   std::auto_ptr<X> x(new X()) ;    // 2.  basic : can throw with new and X constructor
   X * px = x.get() ;               // 2'. nothrow/nofail
   t.list.push_back(px) ;           // 3.  strong : can throw
   x.release() ;                    // 3'. nothrow/nofail
   px->doSomethingThatCanThrow() ;  // 4.  basic : can throw
}

Teraz nasz kod oferuje "podstawową" gwarancję. Nic nie wycieknie, a wszystkie obiekty będą w prawidłowym stanie. Ale możemy zaoferować więcej, czyli silną gwarancję. To jest miejsce, gdzie może stać się kosztowne, i dlatego nie wszystkie kod C++ jest silny. Spróbujmy:

void doSomething(T & t)
{
   // we create "x"
   std::auto_ptr<X> x(new X()) ;    // 1. basic : can throw with new and X constructor
   X * px = x.get() ;               // 2. nothrow/nofail
   px->doSomethingThatCanThrow() ;  // 3. basic : can throw

   // we copy the original container to avoid changing it
   T t2(t) ;                        // 4. strong : can throw with T copy-constructor

   // we put "x" in the copied container
   t2.list.push_back(px) ;          // 5. strong : can throw
   x.release() ;                    // 6. nothrow/nofail
   if(std::numeric_limits<int>::max() > t2.integer)  // 7.   nothrow/nofail
      t2.integer += 1 ;                              // 7'.  nothrow/nofail

   // we swap both containers
   t.swap(t2) ;                     // 8. nothrow/nofail
}

Ponownie uporządkowaliśmy operacje, najpierw tworząc i ustawiając X na odpowiednią wartość. Jeśli jakakolwiek operacja się nie powiedzie, to t nie jest modyfikowana, więc operacje od 1 do 3 można uznać za "silne": jeśli coś rzuca, t nie jest modyfikowana i X nie wycieka, ponieważ jest własnością inteligentnego wskaźnika.

Następnie tworzymy kopię t2 z t i pracujemy nad tą kopią od operacji 4 do 7. Jeśli coś rzuca, {[12] } jest modyfikowane, ale wtedy {[9] } jest nadal oryginałem. Nadal oferujemy silną gwarancję.

Następnie zamieniamy t i t2. Operacje swapowe nie powinny być wykonywane w C++, więc miejmy nadzieję, że Zamiana, dla której napisałeś T, jest nothrow (jeśli nie jest, przepisz ją tak, aby była nothrow).

Więc, jeśli osiągniemy koniec funkcji, wszystko się powiodło (nie ma potrzeby zwracania typu) i t ma swoją wyjątkową wartość. Jeśli się nie powiedzie, to t nadal ma swoją pierwotną wartość.

Teraz oferowanie silnej gwarancji może być dość kosztowne, więc nie staraj się oferować silnej gwarancji dla całego kodu, ale jeśli możesz to zrobić bez kosztów (i C++ inlining i inne optymalizacja może sprawić, że cały powyższy kod), następnie zrób to. Użytkownik funkcji podziękuje Ci za to.

Podsumowanie

Pisanie kodu bezpiecznego dla WYJĄTKÓW wymaga pewnego nawyku. Musisz ocenić gwarancję oferowaną przez każdą instrukcję, a następnie musisz ocenić gwarancję oferowaną przez listę instrukcji.

Oczywiście kompilator C++ nie cofnie gwarancji (w moim kodzie oferuję gwarancję jako tag @ warning doxygen), co jest trochę smutne, ale powinno nie powstrzymuje cię przed próbą napisania kodu bezpiecznego dla WYJĄTKÓW.

Normalna awaria vs. bug

Jak programista może zagwarantować, że funkcja bezawaryjna zawsze się powiedzie? W końcu funkcja może mieć błąd.

To prawda. Gwarancje WYJĄTKÓW powinny być oferowane przez kod wolny od błędów. Ale wtedy, w dowolnym języku, wywołanie funkcji zakłada, że funkcja jest wolna od błędów. Żaden zdrowy kod nie chroni się przed możliwością wystąpienia błędu. Napisz kod najlepiej ty może, a następnie zaoferować gwarancję z założeniem, że jest wolna od błędów. A jeśli jest błąd, popraw go.

Wyjątki dotyczą wyjątkowej awarii przetwarzania, a nie błędów kodu.

Ostatnie słowa

Pytanie brzmi: "czy to jest tego warte ?". Oczywiście, że tak. Posiadanie funkcji "nothrow/no-fail" wiedząc, że funkcja nie zawiedzie jest wielkim dobrodziejstwem. To samo można powiedzieć o" silnej " funkcji, która umożliwia pisanie kodu z semantyką transakcyjną, podobnie jak bazy danych, z funkcjami commit/rollback, commit jest normalnym wykonaniem kodu, a wyjątki są wycofaniem.

Wtedy "podstawowy" jest najmniejszą gwarancją, którą powinieneś zaoferować. C++ jest tam bardzo silnym językiem, z jego zakresami, pozwalającymi uniknąć wycieków zasobów (coś, co Śmieciarz byłby trudny do zaoferowania dla bazy danych, połączenia lub uchwytów plików).

Więc, z tego co widzę, tojest warte to.

Edit 2010-01-29: o wymianie bez rzucania

Nobar napisał komentarz, który moim zdaniem jest dość istotny, ponieważ jest częścią "Jak napisać bezpieczny kod wyjątku": {]}
  • [ja] Zamiana nigdy nie zawiedzie (nawet nie pisz wymiany rzucającej)
  • [nobar] jest to dobra rekomendacja dla niestandardowych funkcji swap(). Należy jednak zauważyć, że std::swap() może zawieść w oparciu o operacje, których używa wewnętrznie

Domyślne std::swap wykonuje kopie i zadania, które dla niektórych obiektów mogą rzucać. Tak więc, domyślna zamiana może rzucać, albo używana dla Twoich klas, albo nawet dla klas STL. Jeśli chodzi o standard C++, operacja swap dla vector, deque, i list nie rzuci, podczas gdy może dla map jeśli funktor porównawczy może rzucić na budowę kopii (Patrz język programowania C++, Wydanie Specjalne, dodatek E, E. 4. 3.Swap ).

Patrząc na implementację Visual C++ 2008 swap wektora, swap wektora nie rzuci, jeśli dwa wektory mają ten sam alokator (tj. normalny przypadek), ale zrobi kopie, jeśli mają różne alokatory. I dlatego zakładam, że może dorzucić tę ostatnią sprawę.

Tak więc oryginalny tekst nadal zawiera: nigdy nie pisz wymiany rzucającej, ale komentarz nobara musi zostać zapamiętany: upewnij się, że obiekty, które wymieniasz, mają wymianę Nie rzucającą.

Edycja 2011-11-06: ciekawy artykuł

Dave W 2007 roku, w wyniku połączenia z Internetem STL, w 2008 roku, w wyniku połączenia z Internetem STL, w 2009 roku, w wyniku połączenia z Internetem STL, w 2009 roku, w wyniku połączenia z Internetem STL, w 2009 roku, w 2009 roku, w 2009 roku]}

Http://www.boost.org/community/exception_safety.html

Spójrz na siódmy punkt (automatyczne testy dla bezpieczeństwa WYJĄTKÓW), gdzie opiera się na automatycznych testach jednostkowych, aby upewnić się, że każdy przypadek jest testowany. Myślę, że ta część jest doskonałą odpowiedzią na pytanie autora " czy możesz być nawet pewien, że to jest?".

Edit 2013-05-31: komentarz od dionadar

t.integer += 1; jest bez gwarancji, że przepełnienie nie stanie się nie wyjątek bezpieczny, a w rzeczywistości może technicznie wywołać UB! (Signed overflow to UB: C++11 5/4 "jeśli podczas oceny wyrażenia wynik nie jest zdefiniowany matematycznie lub nie mieści się w zakresie reprezentowalnych wartości dla jego typu, zachowanie jest niezdefiniowane.") Zauważ, że unsigned integer nie przepełnia się, ale wykonuje swoje obliczenia w klasie równoważności modulo 2^#bity.

Dionadar odnosi się do poniższej linii, która rzeczywiście Ma nieokreślone zachowanie.

   t.integer += 1 ;                 // 1. nothrow/nofail

Rozwiązaniem jest sprawdzenie, czy liczba całkowita jest już na swojej maksymalnej wartości (używając std::numeric_limits<T>::max()) przed dodaniem.

Mój błąd trafiłby do sekcji "normalna awaria a błąd", czyli błąd. Nie unieważnia to rozumowania i nie oznacza, że kod bezpieczny dla wyjątków jest bezużyteczny, ponieważ niemożliwy do osiągnięcia. Ty nie możesz zabezpieczyć się przed wyłączeniem komputera, błędami kompilatora, a nawet Twoimi błędami lub innymi błędami. Nie można osiągnąć doskonałości, ale można spróbować dostać się jak najbliżej.

Poprawiłem kod mając na uwadze komentarz Dionadara.

 496
Author: paercebal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-03 06:30:31

Pisanie kodu bezpiecznego dla wyjątków w C++ nie polega na używaniu wielu bloków try {} catch { }. Chodzi o udokumentowanie, jakie gwarancje zapewnia twój kod.

Polecam lekturę serii Herb Sutter Guru Tygodnia , w szczególności w odsłonach 59, 60 i 61.

Podsumowując, istnieją trzy poziomy bezpieczeństwa wyjątków, które możesz zapewnić:

  • Basic: gdy twój kod rzuca wyjątek, Twój kod nie wycieka zasobów, a obiekty pozostają zniszczalne.
  • Strong: gdy kod rzuca wyjątek, pozostawia stan aplikacji bez zmian.
  • No throw: Twój kod nigdy nie wyrzuca WYJĄTKÓW.

Osobiście odkryłem te artykuły dość późno, więc wiele z mojego kodu C++ na pewno nie jest bezpieczne.

 30
Author: Joh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-12-05 20:37:14

Niektórzy z nas używają wyjątków od ponad 20 lat. PL / mam je np. Założenie, że są one nową i niebezpieczną technologią wydaje mi się wątpliwe.

 17
Author: bmargulies,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-12-05 20:03:25

Po pierwsze (jak stwierdził Neil), SEH jest strukturyzowaną obsługą WYJĄTKÓW Microsoftu. Jest podobny, ale nie identyczny z przetwarzaniem WYJĄTKÓW w C++. W rzeczywistości, musisz włączyć obsługę wyjątków C++ , jeśli chcesz to zrobić w Visual Studio - domyślne zachowanie nie gwarantuje, że lokalne obiekty zostaną zniszczone we wszystkich przypadkach! W obu przypadkach Obsługa wyjątków nie jest tak naprawdę trudniejsza , jest po prostu Inna .

Teraz dla Twojego rzeczywistego pytania.

Czy naprawdę piszesz bezpieczny kod WYJĄTKÓW?

Tak. Dążę do bezpiecznego kodu wyjątkowego we wszystkich przypadkach. Ewangelizuję za pomocą technik RAII w celu uzyskania dostępu do zasobów (np., boost::shared_ptr dla pamięci, boost::lock_guard do blokowania). Ogólnie rzecz biorąc, konsekwentne stosowanie technik RAII i ochrony zakresu znacznie ułatwi pisanie bezpiecznego kodu WYJĄTKÓW. Sztuczka polega na tym, aby dowiedzieć się, co istnieje i jak go zastosować.

Czy jesteś pewien, że twój ostatni kod "gotowy do produkcji" jest bezpieczny dla WYJĄTKÓW?

Nie. Jest tak samo bezpieczny jak jest. Mogę powiedzieć, że nie widziałem błędu procesu z powodu wyjątku od kilku lat aktywności 24/7. Nie oczekuję idealnego kodu, tylko dobrze napisanego kodu. Oprócz zapewnienia bezpieczeństwa WYJĄTKÓW, powyższe techniki gwarantują poprawność w sposób prawie niemożliwy do osiągnięcia z try/catch bloki. Jeśli łapiesz wszystko w swoim górnym zakresie kontroli (wątek, proces itp.), wtedy możesz być pewien, że będziesz nadal działać w obliczu WYJĄTKÓW ( przez większość czasu ). Te same techniki pomogą Ci również kontynuować prawidłowe działanie w obliczu WYJĄTKÓW BEZ try/catch blocks everywhere .

Możesz być w ogóle pewien, że tak jest?

Tak. Możesz być pewien przez gruntowny audyt kodu, ale nikt tak naprawdę tego nie robi? Regularne recenzje kodu i uważni Programiści go a ale daleko do tego.

Czy wiesz i / lub faktycznie używać alternatyw, które działają?

Próbowałem kilku zmian na przestrzeni lat, takich jak Stany kodowania w górnych bitach (ala HRESULTs ) lub to straszne setjmp() ... longjmp() hack. Oba te rozpadają się w praktyce, choć na zupełnie inne sposoby.


W końcu, jeśli masz w zwyczaju stosowania kilku technik i starannie myśleć o tym, gdzie można rzeczywiście zrób coś w odpowiedzi na wyjątek, skończysz z bardzo czytelnym kodem, który jest bezpieczny dla WYJĄTKÓW. Możesz to podsumować, postępując zgodnie z tymi zasadami:

  • You only want to see try/catch Kiedy możesz zrobić coś z konkretnym wyjątkiem
  • prawie nigdy nie chcesz zobaczyć raw new lub delete w kodzie
  • Eschew std::sprintf, snprintf, i tablic w ogóle-używaj std::ostringstream do formatowania i zastępowania tablic przez std::vector i std::string
  • gdy masz wątpliwości, Szukaj funkcjonalność w Boost lub STL przed uruchomieniem własnego]}

Mogę tylko polecić, abyś nauczył się poprawnie używać wyjątków i zapomniał o kodach wynikowych, jeśli planujesz pisać w C++. Jeśli chcesz uniknąć WYJĄTKÓW, warto rozważyć napisanie w innym języku, który albo nie ma ich lub czyni je bezpiecznymi . Jeśli chcesz naprawdę nauczyć się w pełni korzystać z C++, przeczytaj kilka książek z Herb Sutter, Nicolai Josuttis , i Scott Meyers .

 16
Author: D.Shawley,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-12-05 21:00:37

Nie jest możliwe zapisanie kodu bezpiecznego dla WYJĄTKÓW przy założeniu, że "każda linia może rzucać". Konstrukcja kodu bezpiecznego dla WYJĄTKÓW opiera się krytycznie na pewnych umowach/gwarancjach, których powinieneś oczekiwać, przestrzegać, przestrzegać i wdrożyć w swoim kodzie. Absolutnie konieczne jest posiadanie kodu, który gwarantuje Nigdy rzut. Istnieją inne rodzaje gwarancji WYJĄTKÓW.

Innymi słowy, tworzenie kodu bezpiecznego dla wyjątków jest w dużej mierze kwestią program Projektowanie nie tylko kwestia zwykłego kodowania .

 9
Author: AnT,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-12-05 21:09:32
  • Czy naprawdę piszesz bezpieczny kod wyjątku?
Cóż, z pewnością mam taki zamiar.
  • Czy jesteś pewien, że twój ostatni kod "gotowy do produkcji" jest bezpieczny dla WYJĄTKÓW?

Jestem pewien, że moje serwery 24/7 zbudowane przy użyciu WYJĄTKÓW działają 24/7 i nie wyciekają pamięci.

    Czy możesz być w ogóle pewien, że tak jest?

Bardzo trudno jest mieć pewność, że jakikolwiek kod jest poprawny. Zazwyczaj można przejść tylko przez Wyniki

  • Czy wiesz i / lub faktycznie używasz alternatywy, które działają?
Nie. Używanie wyjątków jest czystsze i łatwiejsze niż jakakolwiek alternatywa, z której korzystałem w ciągu ostatnich 30 lat w programowaniu.
 7
Author: anon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-12-05 20:09:47

Pomijając zamieszanie między wyjątkami SEH i C++, musisz mieć świadomość, że wyjątki mogą być wyrzucane w dowolnym momencie i napisać swój kod mając to na uwadze. Potrzeba bezpieczeństwa wyjątków jest w dużej mierze tym, co napędza korzystanie z RAII, inteligentnych wskaźników i innych nowoczesnych technik C++.

Jeśli zastosujesz się do ustalonych wzorców, pisanie kodu bezpiecznego dla WYJĄTKÓW nie jest szczególnie trudne, a w rzeczywistości jest łatwiejsze niż pisanie kodu, który obsługuje błędy we wszystkich przypadkach.

 5
Author: Mark Bessey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-12-05 20:10:42

Eh jest dobre, ogólnie. Ale implementacja C++nie jest zbyt przyjazna, ponieważ naprawdę trudno powiedzieć, jak dobry jest Twój wyjątek. Java na przykład ułatwia to, kompilator będzie miał tendencję do niepowodzenia, jeśli nie obsłużysz możliwych WYJĄTKÓW .

 4
Author: Mr. Boy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-01-29 10:59:16

Bardzo lubię pracować z Eclipse i Javą (nowość w Javie), ponieważ wyrzuca błędy w edytorze, jeśli brakuje obsługi EH. To znacznie utrudnia zapomnienie o wyjątku...

Plus, Z Narzędziami IDE, dodaje blok try / catch lub inny blok catch automatycznie.

 2
Author: Crowe T. Robot,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-12-05 20:11:10

Niektórzy z nas wolą języki takie jak Java, które zmuszają nas do deklarowania wszystkich wyjątków rzucanych przez metody, zamiast czynić je niewidzialnymi, jak w C++ i C#.

Kiedy wykonywane są prawidłowo, wyjątki są lepsze od kodów zwracania błędów, jeśli nie z innego powodu niż nie musisz ręcznie propagować błędów w łańcuchu połączeń.

Mając to na uwadze, niskopoziomowe programowanie bibliotek API powinno prawdopodobnie unikać obsługi wyjątków i trzymać się kodów zwracania błędów.

It ' s been my doświadczenie, że trudno jest napisać czysty kod obsługi wyjątków w C++. Często używam new(nothrow).

 2
Author: David R Tribble,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-12-05 20:12:19

Staram się jak najlepiej napisać bezpieczny dla WYJĄTKÓW kod, tak.

To znaczy, że dbam o to, aby mieć oko naKtóre linie mogą rzucać. Nie każdy może, i to jest niezwykle ważne, aby mieć to na uwadze. Kluczem jest naprawdę myśleć i zaprojektować swój kod, aby zaspokoić, wyjątki Gwarancje określone w standardzie.

Czy ta operacja może być napisana w celu zapewnienia silnej gwarancji wyjątku? Czy muszę zadowolić się podstawowym? Które linie mogą rzucać wyjątki i Jak mogę się upewnić, że jeśli tak się stanie, nie uszkodzą obiektu?

 2
Author: jalf,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-12-06 10:52:51
  • Czy naprawdę piszesz bezpieczny kod wyjątku? [Nie ma czegoś takiego. Wyjątki są papierową osłoną błędów, chyba że masz zarządzane środowisko. Dotyczy to pierwszych trzech pytań.]

  • Czy wiesz i / lub faktycznie używać alternatyw, które działają? [Alternatywa dla czego? Problem polega na tym, że ludzie nie oddzielają rzeczywistych błędów od normalnego działania programu. Jeśli jest to normalne działanie programu (tj. nie znaleziono pliku), to tak naprawdę nie jest to obsługa błędów. Jeśli jest to rzeczywista błąd, nie ma sposobu, aby go "obsłużyć" lub nie jest to rzeczywisty błąd. Twoim celem jest dowiedzieć się, co poszło nie tak i albo zatrzymać arkusz kalkulacyjny i zarejestrować błąd, zrestartować sterownik do tostera, lub po prostu modlić się, że jetfighter może nadal latać, nawet gdy jego oprogramowanie jest wadliwe i nadzieję na najlepsze.]

 2
Author: Charles Eli Cheese,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-12-07 02:27:21

Dużo (powiedziałbym nawet, że większość) ludzi.

Co jest naprawdę ważne w wyjątkach, to to, że jeśli nie napiszesz żadnego kodu obsługi-wynik jest całkowicie bezpieczny i dobrze zachowujący się. Zbyt chętny do paniki, ale bezpieczny.

Musisz aktywnie popełniać błędy w manipulatorach, aby dostać coś niebezpiecznego, a tylko złapać(...) {} będzie porównywać do ignorowania kodu błędu.

 0
Author: ima,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-12-06 18:53:24