Obsługa błędów w C++
3 maj 2008 — mavesOstatnio rozmyślałem nad modelem obsługi błędów w moim przyszłym frameworku. Do tej pory każda moja funkcja zwracała wartość logiczną: false w razie niepowodzenia, true w przeciwnym wypadku. Użycie wyglądało mniej więcej tak:
if( !Funkcja() ) // Jeżeli się nie powiodło
{ /* Obsługa błędu */ }
Takie rozwiązanie ma jednak dość poważną wadę: nie otrzymujemy żadnej dodatkowej informacji dotyczącej błędu. Również sam kod nie wygląda w tym przypadku najlepiej, gdyż to rozwiązanie często prowadzi do wielu zagnieżdżonych instrukcji if.
Inne rozwiązanie polega na zwracaniu przez funkcję liczby całkowitej. Wartości ujemne oznaczają wtedy błąd, zaś dodatnie lub zero - powodzenie. Dodatkowo tworzymy enumerację zawierającą przyczyny błędów:
enum ERROR_CODE{ ERR_FILE_NOT_FOUND = -1, ERR_BAD_ARGS = -2, };
Dzięki temu pisząc obsługę błędu mamy informację na temat jego przyczyny:
int e = Funkcja(arg);
if( e == ERR_FILE_NOT_FOUND )
{ /* Nie znaleziono pliku! */ }
else if( e == ERR_BAD_ARGS )
{ /* Nieodpowiednie argumenty! */ }
Jeżeli interesuje nas sam fakt wystąpienia błędu możemy powiadomić o nim użytkownika w taki sposób:
if( Funkcja() < 0 )
{ /* Wystąpił jakiś błąd… */ }
W tym rozwiązaniu nie występuje już problem z przyczyną błędu. Jednak konieczność opakowania niemal każdego wywołania funkcji w oddzielną instrukcję if nie zachęca do jego używania. Mimo to, ten sposób jest z powodzeniem stosowany w wielu bibliotekach.
Trzeci sposób jaki przychodzi mi do głowy to skorzystanie z mechanizmu wyjątków. Dzięki nim otrzymujemy pełną informację o błędzie oraz zgrabny zapis. Dodatkową zaletą jest to, że wyjątki, w przeciwieństwie do zwracanych kodów błędów, nie mogą zostać zignorowane. Przyczynia się to do zwiększenia niezawodności kodu. Wyjątki, w przeciwieństwie do kodu błędu, mogą być rzucane w konstruktorach oraz przeładowanych operatorach. Oczywiście nie ma rzeczy idealnych. Podobnie jest z wyjątkami - ich użycie wiąże się z pewnym narzutem, w wyniku czego kod wykonuje się nieco wolniej.
Ostatecznie, po długich rozważaniach, zdecyduję się na trzecie rozwiązanie, czyli wyjątki.
