サーチ…


構文

  1. try-except:[[[E:ExceptionType doステートメントで]] [else文]以外の[statements]を試してください。 [ステートメント]終了;

    試してみてください:try [statements] finally [statements] end;

メモリリークを避けるための単純なtry..finallyの例

実行中に例外が発生した場合にリソース(メモリなど)が漏れないようfinallytry - 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呼び出しをUseResource3ReleaseResourceが呼び出される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初期化すると、作成されていなければ解放する際にエラーが回避されます。



Modified text is an extract of the original Stack Overflow Documentation
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow