Błędy i obsługi wyjątków (Podręcznik programowania C++ nowoczesny)
W nowoczesnych C++, w większości scenariuszy preferowanym sposobem sprawozdanie i obsługiwać błędy czasu wykonania i błędy logiczne jest użyć wyjątki.Jest to szczególnie ważne, gdy stos może zawierać kilka wywołań funkcji między funkcji, która wykryje błąd i funkcji, która ma kontekstu wiedzieć, jak ją obsługiwać.Wyjątki umożliwiają formalne, dobrze kod, który wykrywa błędy do przekazywania informacji w górę stosu wywołań.
Błędy programu są ogólnie podzielone na dwie kategorie: Błędy logiczne, spowodowane przez programowania pomyłki, na przykład, błąd "indeks poza zakresem" i błędy wykonania, które są poza kontrolą programisty, na przykład błąd "w sieci usługa niedostępna".C styl programowania i COM raportowanie błędów jest zarządzany przez zwrócenie wartości, reprezentującą kod błędu lub kod stanu dla danej funkcji lub ustawiając zmienną globalną, że obiekt wywołujący może opcjonalnie pobrać po każdego wywołania funkcji, aby sprawdzić, czy błędy zostały zgłoszone.Na przykład programowania COM używa zwracana wartość HRESULT do komunikowania się błędy wywołującemu i interfejsu Win32 API ma funkcję GetLastError pobrać ostatniego błędu, która została zgłoszona przez stos wywołań.W obu przypadkach jest do rozmówcy do rozpoznawania kodu i odpowiednio na niego odpowiadać.Jeśli wywołujący jawnie nie obsługują kod błędu, program może crash bez ostrzeżenia, kontynuuj wykonywanie złe dane i generują niepoprawne wyniki.
Wyjątki są preferowane w nowoczesnych C++ z następujących powodów:
Wyjątek wymusza kod wywołujący rozpoznać błąd i je obsłużyć.Nieobsłużone wyjątki zatrzymanie wykonywania programu.
Skok wyjątek do punktu w stos wywołań, który może obsłużyć błędu.Funkcje pośrednie można pozwolić wyjątek, propagowanie.Nie muszą koordynować z innych warstw.
Mechanizm niekontrolowanej stosu wyjątku niszczy wszystkie obiekty w zakresie zgodnie z regułami wyraźnie określone, po jest wyjątek.
Wyjątek umożliwia czystej separacji kod, który wykryje błąd i kod, który obsługuje błąd.
Poniższy uproszczony przykład przedstawiono składnię niezbędne rzuca i przechwytywanie wyjątków C++.
#include <stdexcept>
#include <limits>
#include <iostream>
using namespace std;
class MyClass
{
public:
void MyFunc(char c)
{
if(c < numeric_limits<char>::max())
throw invalid_argument("MyFunc argument too large.");
//...
}
};
int main()
{
try
{
MyFunc(256); //oops!
}
catch(invalid_argument& e)
{
cerr << e.what() << endl;
return -1;
}
//...
return 0;
}
Wyjątki C++ są podobne w językach takich jak C# i Java.W try bloku, jeśli wyjątek jest thrown będzie on złowionych w pierwszym skojarzone catch bloku, którego typ zgodny z wyjątkiem.Innymi słowy, wykonywanie przeskakuje z throw instrukcji do catch instrukcji.Jeśli stwierdzono nie bloku catch można używać, std::terminate jest wywoływana i zamyka program.W języku C++ może zostać wygenerowany dowolnego typu; jednak zaleca się że rzut typ, który pochodzi bezpośrednio lub pośrednio z std::exception.W poprzednim przykładzie typ wyjątku invalid_argument, jest zdefiniowany w biblioteki standardowej w <stdexcept> pliku nagłówka.C++ nie zawiera i nie wymaga, finally bloku, aby upewnić się, że wszystkie zasoby są zwalniane, jeśli jest wyjątek.Nabycie zasobu jest idiom inicjowania (RAII), która używa inteligentne kursory, zapewnia funkcje wymagane dla zasobu oczyszczania.Aby uzyskać więcej informacji, zobacz Jak: Projektowanie dla bezpieczeństwa wyjątek (C++).Informacji na temat mechanizmu niekontrolowanej stosu C++, zobacz Wyjątki i stosu niekontrolowanej w języku C++.
Podstawowe wytyczne
Obsługa błędów niezawodne jest trudne w dowolnym języku programowania.Chociaż wyjątki zapewniają kilka funkcji obsługujących dobrej obsługi błędów, nie mogą one wszystkie prace dla Ciebie.Aby wykorzystać zalety mechanizmu wyjątek, pamiętaj wyjątki podczas projektowania kodu.
Użycia deklaracji rozkazujących do błędów, które nigdy nie powinny występować.Sprawdzanie błędów, które mogą wystąpić na przykład błędy sprawdzania poprawności danych wejściowych na parametry funkcji publicznych za pomocą wyjątków.Aby uzyskać więcej informacji, zobacz Exceptions VS. Assertions.
Kod, który obsługuje błąd, może być oddzielony od kod, który wykryje błąd jednego lub wielu wywołań funkcji interwencyjnym przy wyjątki.Należy rozważyć używanie kodów błędów zamiast w pętli wydajność krytycznych, gdy kod obsługi błędu jest sprzężona ściśle do kodu, który wykrywa go.Aby uzyskać więcej informacji o tym, kiedy nie używać wyjątków, zobacz When Not to Use Exceptions.
Dla każdej funkcji może być throw lub propagować wyjątek, podać jeden gwarancje trzech wyjątek: silne gwarancji, podstawowych gwarancji lub gwarancja nothrow (noexcept).Aby uzyskać więcej informacji, zobacz Jak: Projektowanie dla bezpieczeństwa wyjątek (C++).
Generują wyjątki według wartości, przez odniesienie połowów.Nie połowów nie może obsłużyć.Aby uzyskać więcej informacji, zobacz Wytyczne dotyczące rzuca i przechwytywanie wyjątków (C++).
Nie używaj specyfikacji wyjątków, które zostały zaniechane w C ++ 11.Aby uzyskać więcej informacji, zobacz Exception specifications and noexcept.
Standardowa biblioteka wyjątek typów należy używać, gdy mają zastosowanie.Typy niestandardowe wyjątków od uzyskania wyjątek klasy hierarchii.Aby uzyskać więcej informacji, zobacz Jak: za pomocą standardowych obiektów wyjątek biblioteki.
Nie zezwalaj na wyjątki escape from destruktory lub pamięć dezalokacji funkcji.
Wyjątki i wydajności
Mechanizm wyjątek ma bardzo minimalnej wydajności, kosztów, jeśli nie jest wyjątek.Jeśli wyjątek, koszty przechodzenia stosu i odkręcanie jest porównać koszty wywołania funkcji.Struktury dodatkowe dane są wymagane do śledzenia stosu wywołań po try bloku jest wpisana, i dodatkowe instrukcje są wymagane na odpoczynek stosu, jeśli jest wyjątek.Jednak w większości scenariuszy kosztów wydajność i ilość pamięci nie jest znaczący.Niekorzystny wpływ wyjątków na wydajność jest prawdopodobnie będzie istotne tylko w systemach bardzo ograniczone pamięci lub w wydajność krytycznych pętle Jeżeli błąd jest prawdopodobnie występujących regularnie i kod obsługujący ona ściśle jest sprzężona z kodu, który zgłasza.W każdym przypadku jest niemożliwe znać rzeczywisty koszt wyjątki bez profilowania i pomiaru.Nawet w tych rzadkich przypadkach gdy koszt jest znacząca, możesz może zważyć przeciwko zwiększonej prawidłowości, łatwiejsze łatwość konserwacji i innych korzyści, jakie są dostarczane przez zasady zaprojektowanej wyjątek.
Wyjątki VS. potwierdzeń
Wyjątki i potwierdza, są dwa różne mechanizmy wykrywania błędów czasu wykonywania w programie.Użycia deklaracji rozkazujących do testowania warunków podczas rozwoju, który nigdy nie może być wartość true, jeśli cały kod jest poprawny.Brak obsługi takiego błędu za pomocą wyjątek, ponieważ błąd oznacza coś w kodzie ma być ustalona w punktu i nie stanowią warunek, że program ma odzyskać w czasie wykonywania.Assert zatrzymuje wykonywanie w instrukcji, dzięki czemu można sprawdzić stan programu w debugerze; wyjątek kontynuuje wykonywanie od pierwszego obsługi catch właściwe.Użyj wyjątki warunki błędów, które mogą wystąpić w czasie wykonywania, nawet jeśli kod jest poprawna, na przykład, "nie można odnaleźć pliku" lub "Brak pamięci." Można odzyskać z tych warunków, nawet jeśli odzyskanie tylko komunikat w dzienniku i kończy program.Zawsze sprawdzaj argumenty funkcji publicznych za pomocą wyjątków.Nawet jeśli funkcja jest wolny od błędów, możesz nie mieć pełnej kontroli nad argumenty, które użytkownik może przejść do niego.
Wyjątki C++ a wyjątki SEH systemu Windows
Programy zarówno c i C++ można użyć mechanizm strukturalnej obsługi wyjątków (SEH) w systemie operacyjnym Windows.Pojęcia w SEH w wyjątki C++ podobne, z wyjątkiem, że SEH używa __try, __except, i __finally konstrukcje zamiast try i catch.W programie Visual C++ wyjątki C++ są implementowane dla SEH.Jednak podczas pisania kodu C++, należy użyć składni języka C++ wyjątek.
Aby uzyskać więcej informacji na temat SEH, zobacz Strukturalnej obsługi (C++) wyjątków.
Specyfikacje wyjątek i noexcept
Wyjątek specyfikacje zostały wprowadzone w języku C++ jako sposób wyjątków, które może być throw funkcji.Jednakże wyjątek specyfikacji okazał się w praktyce i zostały zaniechane w C ++ 11 projekt normy.Firma Microsoft zaleca, aby nie używać specyfikacje wyjątku, z wyjątkiem throw(), co oznacza wyjątek zezwala na nie wyjątki escape.Jeśli musisz użyć specyfikacji wyjątek typu throw(typu), należy pamiętać, że Visual C++ odbiega od normy w określony sposób.Aby uzyskać więcej informacji, zobacz Specyfikacje wyjątek.noexcept Specyfikatora jest wprowadzony w C ++ 11 preferowany alternatywne w stosunku do throw().
Zobacz też
Koncepcje
Jak: interfejs między wyjątkowych i wyjątkowych kod