Должен ли я освобождать/уничтожать исключения после обработки исключений?

Я отлаживаю программу 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 с помощью курсора, я все еще могу увидеть его значение. Я ожидал бы, что это было вне рамок и, в конечном счете, уничтожено.

Итак, мой вопрос: должен ли я освобождать/уничтожать исключения после обработки исключений?

Ответ 1

Среда выполнения берет на себя ответственность за исключения после их повышения. Вам не нужно их освобождать.

Исключение уничтожается в конце блока, в котором он обрабатывается, как показано в этой программе:

{$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: Boo
MyException.Destroy
After try/except block

Пока отладчик может показать вам информацию об исключении после его освобождения, это поведение undefined. Компилятор понимает, что исключение оставило область видимости, даже если отладчик не знает этого факта.


Если вы хотите, чтобы время жизни исключения превышало блок except, который обрабатывает его, вам нужно будет вызвать AcquireExceptionObject. Как только вы это сделаете, ваша ответственность освободит исключение, чье жизненное время вы приобрели.

Ответ 2

Компилятор + RTL позаботится об этом для вас, поэтому нет.

Что касается объекта e: Exception, который по-прежнему остается "действительным" после окончания блока except, см. этот вопрос:

Почему объекты Delphi назначаются даже после вызова .Free?

Уничтожение чего-то не гарантирует, что память немедленно недействительна, она просто делает ее доступной для повторного использования.