Zgłaszanie i obsługa wyjątków


Aby wykreować obiekt wyjątku, należy wywołać konstruktora klasy wyjątku w instrukcji raise. Przykład:

raise EMathError.Create;

Ogólna postać instrukcji raise:

raise object at address

gdzie object i at address są opcjonalne. Jeśli object pominięto, instrukcja powtórnie wywołuje bieżący wyjątek. Jeśli wyspecyfikowano address, jest to zwykle wskaźnik do procedury lub funkcji; używa się tej opcji do zgłoszenia wyjątku z wcześniejszego punktu w stosie niż ten, w którym zdarza się bieżący błąd.

Kiedy zgłaszany jest wyjątek, ten którego odwołanie zamieszczone jest w instrukcji raise, jego obsługa jest przeprowadzana wg normalnej procedury obsługi wyjątków. Instrukcja raise nigdy nie zwraca kontroli w zwykły sposób. Zamiast tego, przenosi ona kontrolę do wewnętrznej procedury obsługi wyjątków (exception handler), która potrafi obsłużyć wyjątek danej klasy. (Wewnętrzny handler to ten, którego blok try...except wykonywany był (najbardziej) ostatnio, a którego egzekucji jeszcze nie zakończono.)

Przykładowo, funkcja poniżej konwertuje łańcuch znaków na liczbę całkowitą, zgłaszając wyjątek ERangeError jeśli wartość rezultatu jest poza wyspecyfikowanym zakresem.

function StrToIntRange(const S: string; Min, Max: Longint): Longint;
begin
  Result := StrToInt(S);  // StrToInt zadeklarowano w SysUtils
  if (Result < Min) or (Result > Max) then
    raise ERangeError.CreateFmt(
      '%d is not within the valid range of %d..%d',
      [Result, Min, Max]);
end;

Należy zwrócić uwagę na metodę CreateFmt wywoływaną w instrukcji raise. Wyjątek i jego typy potomne mają specjalne konstruktory, które dostarczają alternatywnych sposobów wykreowania komunikatów wyjątku i identyfikatorów kontekstu (context ID).

Zgłoszony wyjątek jest niszczony automatycznie po jego obsłużeniu. Nigdy nie należy próbować niszczyć zgłoszonego wyjątku "ręcznie".

Uwaga! Wywoływanie wyjątku w sekcji initialization modułu może nie odnieść zamierzanego skutku. Implementacja wyjątków zamieszczona jest w module SysUtils, który musi być zainicjowany zanim będzie udostępniony. Jeśli wyjątek zdarza się podczas inicjowania, wszystkie inicjowane moduły zawierające deklaracje SysUtils są finalizowane (wykonywana jest ich sekcja finalization) i wykonywane jest powtórne wywołanie wyjątku. Wtedy moduł System przechwytuje wyjątek i obsługuje go, zwykle przez przerwanie programu.


Instrukcja Try...except
Zagnieżdzone wyjątki
Instrukcja Try...finally