Embarcadero Delphi
try、except、およびfinallyの使用
サーチ…
構文
try-except:[[[E:ExceptionType doステートメントで]] [else文]以外の[statements]を試してください。 [ステートメント]終了;
試してみてください:try [statements] finally [statements] end;
メモリリークを避けるための単純なtry..finallyの例
実行中に例外が発生した場合にリソース(メモリなど)が漏れないようfinally 、 try - finallyを使用してtry 。
以下の手順では、文字列をファイルに保存し、 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;
ファイルの保存中に例外が発生するかどうかにかかわらず、 SLは解放されます。例外は呼び出し元に送られます。
新しいオブジェクトの例外セーフ戻り
関数がオブジェクトを返すとき(呼び出し側が渡したものを使用するのではなく)、例外がオブジェクトをリークさせないように注意してください。
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;
ナイーブなプログラマは、すべての例外タイプをキャッチしてそのような関数からnilを返そうとするかもしれませんが、それはすべての例外タイプを処理せずにすべての例外タイプをキャッチするという、
試してみてください。
try - finallyブロックは、 try - exceptブロックの中にネストすることができます。
try
AcquireResources;
try
UseResource;
finally
ReleaseResource;
end;
except
on E: EResourceUsageError do begin
HandleResourceErrors;
end;
end;
UseResource内で例外が発生すると、実行はReleaseResourceジャンプします。例外がEResourceUsageError場合、実行は例外ハンドラにジャンプし、 HandleResourceErrorsを呼び出しHandleResourceErrors 。他の型の例外は上記の例外ハンドラをスキップし、次のtryバブルアップします - 呼び出しスタックexceptブロックするexceptます。
例外AcquireResourceまたはReleaseResource実行をスキップして、例外ハンドラに行くことになりますfinallyブロックする、のいずれかに対応するためtryブロックは、まだ入力されていないかので、 finallyブロックがすでに入力されています。
試してみる
try - exceptブロックは、 try - finallyブロック内にネストすることができます。
AcquireResource;
try
UseResource1;
try
UseResource2;
except
on E: EResourceUsageError do begin
HandleResourceErrors;
end;
end;
UseResource3;
finally
ReleaseResource;
end;
場合EResourceUsageErrorで発生UseResource2 、実行は例外ハンドラにジャンプして呼び出しますHandleResourceError 。例外は処理されたとみなされるため、実行はUseResource3に続いてReleaseResource続きます。
UseResource2で他の型の例外が発生したUseResource2 、ここに表示される例外ハンドラは適用されません。したがって、実行はUseResource3呼び出しをUseResource3 、 ReleaseResourceが呼び出されるfinallyブロックに直接移動します。その後、例外がコールスタックをバブルアップするので、実行は次の適用可能な例外ハンドラにジャンプします。
上の例で他の呼び出しで例外が発生した場合、 HandleResourceErrorsは呼び出されません。これは、その例外ハンドラに対応するtryブロック内で他の呼び出しが発生しないためです。
2つ以上のオブジェクトを試してみてください
Object1 := nil;
Object2 := nil;
try
Object1 := TMyObject.Create;
Object2 := TMyObject.Create;
finally
Object1.Free;
Object2.Free;
end;
try-finallyブロックの外側でnilてオブジェクトを初期化しないtry-finally 、そのうちの1つが作成されなかった場合、AVはfinallyブロックで発生します。なぜなら、オブジェクトは(初期化されていないので)例外が発生します。
Freeメソッドは、オブジェクトがnilであるかどうかをチェックするので、両方のオブジェクトをnil初期化すると、作成されていなければ解放する際にエラーが回避されます。