Embarcadero Delphi
Użyj try, z wyjątkiem i nareszcie
Szukaj…
Składnia
Try-wyjątkiem: spróbuj [instrukcje] oprócz [[[na E: ExceptionType do instrukcja]] [else instrukcja] | [wyciągi] koniec;
Spróbuj na końcu: spróbuj [instrukcje] w końcu [instrukcje] koniec;
Prosty przykład ... na koniec, aby uniknąć wycieków pamięci
Użyj try
- finally
aby uniknąć wycieku zasobów (takich jak pamięć) na wypadek wystąpienia wyjątku podczas wykonywania.
Poniższa procedura zapisuje ciąg znaków w pliku i zapobiega wyciekaniu TStringList
.
procedure SaveStringToFile(const aFilename: TFilename; const aString: string);
var
SL: TStringList;
begin
SL := TStringList.Create; // call outside the try
try
SL.Text := aString;
SL.SaveToFile(aFilename);
finally
SL.Free // will be called no matter what happens above
end;
end;
Bez względu na to, czy podczas zapisywania pliku wystąpi wyjątek, SL
zostanie zwolnione. Każdy wyjątek trafi do dzwoniącego.
Wyjątkowo bezpieczny zwrot nowego obiektu
Gdy funkcja zwraca obiekt (w przeciwieństwie do używania obiektu przekazanego przez program wywołujący), należy zachować ostrożność, wyjątek nie powoduje przecieku obiektu.
function MakeStrings: TStrings;
begin
// Create a new object before entering the try-block.
Result := TStringList.Create;
try
// Execute code that uses the new object and prepares it for the caller.
Result.Add('One');
MightThrow;
except
// If execution reaches this point, then an exception has occurred. We cannot
// know how to handle all possible exceptions, so we merely clean up the resources
// allocated by this function and then re-raise the exception so the caller can
// choose what to do with it.
Result.Free;
raise;
end;
// If execution reaches this point, then no exception has occurred, so the
// function will return Result normally.
end;
Naiwni programiści mogą próbować wychwycić wszystkie typy wyjątków i zwrócić nil
z takiej funkcji, ale to tylko szczególny przypadek ogólnej zniechęconej praktyki łapania wszystkich typów wyjątków bez ich obsługi.
Try-wreszcie zagnieżdżone w try-wyjątkiem
Blok try
- finally
może być zagnieżdżony w try
- except
bloku.
try
AcquireResources;
try
UseResource;
finally
ReleaseResource;
end;
except
on E: EResourceUsageError do begin
HandleResourceErrors;
end;
end;
Jeśli wyjątek wystąpi w UseResource
, wykonanie przeskoczy do ReleaseResource
. Jeśli wyjątek to EResourceUsageError
, wówczas wykonanie przeskoczy do modułu obsługi wyjątków i HandleResourceErrors
. Wyjątki dowolnego innego typu pomijają procedurę obsługi wyjątków powyżej i przechodzą do kolejnej try
- except
blokowania stosu wywołań.
Wyjątki w AcquireResource
lub ReleaseResource
spowoduje wykonanie przejść do obsługi wyjątków, omijając finally
blok, albo dlatego, że odpowiada try
blok nie został jeszcze wprowadzony albo dlatego, że finally
blok został już wprowadzony.
Spróbuj, z wyjątkiem zagnieżdżonego w środku spróbuj na końcu
Blok try
- except
może być zagnieżdżony w bloku try
- finally
.
AcquireResource;
try
UseResource1;
try
UseResource2;
except
on E: EResourceUsageError do begin
HandleResourceErrors;
end;
end;
UseResource3;
finally
ReleaseResource;
end;
Jeśli EResourceUsageError
wystąpi w UseResource2
, wówczas wykonanie przeskoczy do modułu obsługi wyjątków i HandleResourceError
. Wyjątek zostanie uznany za obsłużony, więc wykonanie będzie kontynuowane w UseResource3
, a następnie ReleaseResource
.
Jeśli wyjątek innego typu wystąpi w UseResource2
, pokaz obsługi wyjątków tutaj nie będzie miał zastosowania, więc wykonanie przeskoczy nad wywołaniem UseResource3
i przejdzie bezpośrednio do bloku finally
, gdzie zostanie ReleaseResource
. Następnie wykonanie przeskoczy do następnego odpowiedniego modułu obsługi wyjątków, gdy wyjątek pojawi się na stosie wywołań.
Jeśli wystąpi wyjątek w jakimkolwiek innym wywołaniu w powyższym przykładzie, HandleResourceErrors
nie zostanie wywołany. Jest tak, ponieważ żadne inne wywołanie nie występuje w bloku try
odpowiadającym temu programowi obsługi wyjątków.
Spróbuj na końcu z 2 lub więcej obiektami
Object1 := nil;
Object2 := nil;
try
Object1 := TMyObject.Create;
Object2 := TMyObject.Create;
finally
Object1.Free;
Object2.Free;
end;
Jeśli nie zainicjujesz obiektów nil
poza blokiem try-finally
, jeśli jeden z nich nie zostanie utworzony, AV pojawi się w bloku ostatecznie, ponieważ obiekt nie będzie zerowy (ponieważ nie został zainicjowany) i spowoduje wyjątek.
Metoda Free
sprawdza, czy obiekt nie ma wartości zerowej, więc inicjowanie obu obiektów wartością nil
pozwala uniknąć błędów podczas uwalniania ich, jeśli nie zostały utworzone.