2013-07-18 26 views
11

Sto eseguendo il debug di un programma delphi.Devo liberare/distruggere le eccezioni dopo la gestione delle eccezioni?

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

Prendo un'Escetion e faccio ciò di cui ho bisogno. Ora, quando il contatore del programma di debug raggiunge la linea appena sotto end;, se si posiziona con il cursore su e.errorCode, posso ancora vedere il suo valore. Mi aspetterei che questo fosse fuori portata e, alla fine, distrutto.

Quindi, la mia domanda è: devo liberare/distruggere le eccezioni dopo la gestione delle eccezioni?

+4

Si prega di considerare di sollevare tale eccezione nel caso in cui il codice di errore * non sia * 1104. Attualmente il codice * ignora silenziosamente * tutti gli altri errori. –

+0

Non solo errorCode, @RobKennedy, ma anche altri tipi di eccezioni devono essere gestiti. –

+0

No, Paolo. Il tuo codice attuale già * ignora * altri tipi di eccezioni, che è il ** comportamento corretto **. Non ricevere mai un'eccezione a meno che tu non stia scrivendo il codice per * risolvere * il problema che ha causato l'eccezione. Se non puoi aggiustarlo, allora non prenderlo; altrimenti, il codice più in alto nello stack delle chiamate è * negato * l'opportunità di risolverlo. –

risposta

15

Il runtime diventa proprietario delle eccezioni dopo che sono state sollevate. Non è necessario liberarli.

L'eccezione viene distrutto alla fine del blocco in cui viene gestita, come dimostrato da questo programma:

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

che emette:

 
MyException: Boo 
MyException.Destroy 
After try/except block 

Mentre il debugger può ancora mostrare informazioni sull'eccezione dopo che è stata liberata, tale comportamento non è definito. Il compilatore comprende che l'eccezione ha lasciato l'ambito, anche se il debugger non è a conoscenza di ciò.


Se si desidera la vita di un'eccezione di estendere oltre il blocco except che gestisce allora si avrebbe bisogno di chiamare AcquireExceptionObject. Una volta che lo fai, diventa tua responsabilità liberare l'eccezione di cui hai acquisito la vita.

+0

Buono il punto di AcquireExceptionObject, perché è in argomento con la domanda. –

+0

La documentazione di 'AcquireExceptionObject' indica anche che le eccezioni sono conteggiate con riferimento e che aumenta il conteggio ref. 'ReleaseExceptionObject' d'altra parte diminuisce il numero di ref. Quando il conteggio ref raggiunge lo zero, l'eccezione verrà liberata. –

+0

Di solito non ti interessa, dal momento che il compilatore lo gestisce per te, ma come dice David è possibile gestire manualmente la durata di un oggetto eccezione oltre il blocco delle eccezioni con queste funzioni. –

5

Il compilatore + RTL si occupa di questo per te, quindi non farlo.

Per quanto riguarda l'oggetto e: Exception ancora beeing "valido" dopo la fine del blocco di eccezione, vedi questa domanda:

Why are Delphi objects assigned even after calling .Free?

distruggere qualcosa non garantisce che la memoria sia immediatamente invalidata, semplicemente lo rende disponibile per il riutilizzo.