The Delphi Bug List

Entry No.
635
コンパイラ - コード生成
'finally' ブロックで例外を生成すると、メモリリークが起こる
1.02 2.01 3.0 3.01 3.02 4.0 4.01 4.02 4.03 5.0 5.01 6.0 6.01 6.02 Kylix 1.0
Unknown Exists Exists Exists Exists Exists Exists Exists Exists Exists Exists Exists Unknown Unknown Unknown
解説
Reported by Andreas Hoerstemeier; checked by Jordan Russell
finally ブロックで例外が発生すると、Delphi はメモリリークを起こします。その後 Delphi は元の例外を完全に忘れてしまい、新しい方の例外は発生しますが、元の例外はヒープ領域から削除されません。
サンプルコード:
try
  try
    raise EZeroDivide.Create('');
  finally
    raise EUnderflow.Create('');
  end; 
except
  on EZeroDivide do writeln('Zero');
  on EUnderflow do writeln('Underflow');
end;

EZeroDivide オブジェクトがヒープに残ったままの状態で、例外ブロックのUnderflowのところまで到達します。これは例外クラスの destroy メソッドをオーバーライドする事で確認出来ます。このようなケースで、どちらの例外がfinallyブロックから出て行くべきかが載っている文献を見つける事は出来ませんでした。どちらでも正しいのかもしれません。

確認者からの注意:
Delphiのヘルプトピック "try..finally 文" には以下ように書かれています。
生成された例外が finally で処理されない場合,その例外は try...finally 文を越えて伝わり,try 節で既に生成されている例外は失われます。したがって,ほかの例外の伝播の妨げにならないよう,ローカルに生成された例外はすべて finally 節で処理するようにしてください。
(訳注: 日本語版 Delphi 5 のヘルプから原文に該当する部分を引用)
しかし、新しい例外の生成がメモリリークを起こすことには言及していません。
ユーザーからのコメント
Jordan Russell
09 Apr 2001  07:31 PM GMT
しばらく考えた後、私はこのエントリーを"混乱の元(Gotcha)"から"バグ(Bug)"に変更することに決めました。

"except" 節で新しい例外が発生しても、メモリリークは起りません。
"finally" 節で新しい例外が発生しても、メモリリークが起こるべきではありません。
Latest update of this entry: 2001-06-19
本家 The Delphi Bug List のエントリーはこちら
The Delphi Bug List 日本語訳 へ