12

我正在调试一个delphi程序。

except
    on e: TErrorTapeDrive do
        if e.errorCode = 1104 then
            if Assigned(indexDoneEvent) then
                indexDoneEvent;
        // other handling...
    // other handling...
end;

我抓住了一个 Excetion e 并做我需要的事情。现在,当调试程序计数器到达下一行时end;,如果我e.errorCode将光标悬停,我仍然可以看到它的值。我预计这超出了范围,并最终被破坏。

所以,我的问题是:我应该在异常处理后释放/销毁异常吗?

4

2 回答 2

18

引发异常后,运行时拥有异常的所有权。您不需要释放它们。

异常在处理它的块的末尾被销毁,如下程序所示:

{$APPTYPE CONSOLE}

uses
  SysUtils;

type
  MyException = class(Exception)
  public
    destructor Destroy; override;
  end;

destructor MyException.Destroy;
begin
  Writeln('MyException.Destroy');
  inherited;
end;

procedure Main;
begin
  try
    raise MyException.Create('Boo');
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
  Writeln('After try/except block');
end;

begin
  Main;
  Readln;
end.

输出:

我的异常:嘘
MyException.Destroy
在 try/except 块之后

虽然调试器在释放异常后仍可能向您显示有关异常的信息,但该行为是未定义的。编译器知道异常已经离开作用域,即使调试器不知道这个事实。


如果您希望异常的生命周期超出except处理它的块,那么您需要调用AcquireExceptionObject. 一旦你这样做了,你就有责任释放你获得的生命周期的异常。

于 2013-07-18T09:14:18.687 回答
5

编译器 + RTL 会为您解决这个问题,所以不要这样做。

至于e: Exception在 except 块结束后仍然“有效”的对象,请参阅这个问题:

为什么调用 .Free 后还要分配 Delphi 对象?

销毁某些东西并不能保证内存立即失效,它只是使其可供重用。

于 2013-07-18T09:14:31.920 回答