2013-07-18 2 views
11

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

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

Я улавливаю Эксперимент и делаю то, что мне нужно. Теперь, когда счетчик программ отладки достигнет линии чуть ниже end;, если я нахожу e.errorCode с помощью курсора, я все еще вижу его значение. Я ожидал бы, что это было вне рамок и, в конечном счете, уничтожено.

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

+4

Обратите внимание на повторное поднятие этого исключения в случае, если код ошибки * не является * 1104. В настоящее время ваш код * молча игнорирует * все другие ошибки. –

+0

Не только errorCode, @RobKennedy, но и другие типы Исключений. –

+0

Нет, Паоло. Ваш текущий код уже * игнорирует * другие типы исключений, что является ** правильным поведением **. Никогда не поймайте исключение, если вы не пишете код, чтобы * исправить * проблему, вызвавшую исключение. Если вы не можете исправить это, тогда не поймайте его; в противном случае код вверх по стеку вызовов будет * denied * возможность исправить его. –

ответ

15

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

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

{$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 

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


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

+0

Хорошая точка AcquireExceptionObject, потому что в теме есть вопрос. –

+0

Документация 'AcquireExceptionObject' также указывает, что исключения подсчитываются и что количество ссылок увеличивается. С другой стороны, ReleaseExceptionObject уменьшает количество ссылок. Когда число ссылок достигнет нуля, исключение будет освобождено. –

+0

Обычно вам это неинтересно, поскольку компилятор обрабатывает это для вас, но, как говорит Дэвид, с помощью этих функций можно управлять временем жизни объекта исключения за пределами блока исключений. –

5

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

Что касается e: Exception объекта до сих пор неоспоримым «действует» после окончания, за исключением блока, см этот вопрос:

Why are Delphi objects assigned even after calling .Free?

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

Смежные вопросы