Come faccio a far sapere a Delphi che ho già gestito un’eccezione?

Ho impostato Application.OnException su un gestore di eccezioni personalizzato in modo che possa registrare arresti anomali e dare un’opzione per uscire. Tuttavia, ora sto trovando che questo funziona anche su eccezioni che ho già gestito, ad esempio, eccezioni che emergono quando si convalidano gli input numerici. C’è un modo per far sì che il gestore di eccezioni personalizzato venga eseguito solo su eccezioni non gestite?

Modifica: si scopre che ottengo il comportamento previsto quando esco dal debugger. Forse è solo una cosa del debugger. Non trovo che l’interazione del debugger di Delphi con le eccezioni sia intuitiva, per non dire altro.

Se il comportamento cambia dentro e fuori dal debugger, allora non è proprio il tuo programma a dirti delle eccezioni. Ho scritto di questo fenomeno sul mio sito Web:

Perché continuo a ricevere messaggi di errore anche dopo aver scritto un gestore di eccezioni?

Un estratto:

Nelle sue impostazioni predefinite, l’IDE Delphi ti avvisa ogni volta che si verifica un’eccezione nel tuo programma …. Quello che è importante capire è che a quel punto, nessuno dei codici di gestione delle eccezioni del tuo programma è stato ancora eseguito. È tutto Delphi stesso; il suo stato speciale di debugger consente di ottenere la prima notifica di qualsiasi eccezione nel programma, anche prima che il programma ne sia a conoscenza.

Dopo aver chiuso la finestra del messaggio di Delphi, l’esecuzione sarà messa in pausa sulla linea migliore del codice sorgente che Delphi potrebbe trovare per rappresentare la fonte dell’eccezione. Premere il pulsante “Esegui” per riprendere il programma. Il controllo passerà al blocco successivo o finale. Prima di riprendere il tuo programma, puoi utilizzare i vari strumenti di debug a tua disposizione. È ansible esaminare i valori di qualsiasi variabile nell’ambito e persino modificarne i valori.

Quindi, come comunichi a Delphi che hai già gestito un’eccezione? Non lo fai, perché il tuo programma non l’ha ancora gestito . E perché il debugger non può rilevare se il tuo programma gestirà un’eccezione? Perché per farlo, ha bisogno di eseguire ulteriormente il tuo programma. Rilevare la mancanza di un gestore di eccezioni è come risolvere il problema dell’arresto. L’unico modo per determinare se verrà gestita un’eccezione consiste nell’eseguire il programma e quindi verificare se l’eccezione viene gestita. Ma a quel punto, è troppo tardi per fare il debug, quindi il debugger non ha altra scelta che mettere in pausa il tuo programma quando rileva per la prima volta un’eccezione e poi ti permette di capire cosa fare da lì.

Il mio articolo prosegue descrivendo alcuni modi per evitare che il debugger accetti determinate eccezioni, riassunte qui:

  • Utilizzare i punti di interruzione avanzati per distriggersre temporaneamente l’ interruzione delle eccezioni per alcune regioni del codice.
  • Configurare il debugger per ignorare alcune classi di eccezioni (e i loro discendenti).
  • Dì al debugger di non notificarti eventuali eccezioni.
  • Disabilitare del tutto il debug integrato.

C’è un’altra opzione che non ho incluso nel mio articolo:

  • Cambia il tuo programma in modo tale che l’eccezione non venga sollevata in primo luogo.

Dici che stai convalidando l’input numerico. Mi sembra che tu stia facendo qualcosa come chiamare StrToInt e poi prendere l’eccezione EConvertError quando l’input non è un numero intero valido. È un modo costoso per convalidare l’input. Invece di questo, usa TryStrToInt , che ti dirà se la conversione è riuscita, o StrToIntDef , che restituirà automaticamente un valore predefinito invece di generare un’eccezione. Un’altra opzione è la vecchia vecchia Val , che tenta di convertire una stringa, e se fallisce, ti dice quale posizione nella stringa ha causato l’errore. Val è particolarmente utile se si desidera utilizzare quanti più caratteri ansible per la conversione e quindi riprendere l’analisi al successivo carattere non numerico.

Citando dalla documentazione (Delphi 7) su TApplication.OnException

 "Use OnException to change the default behavior that occurs when an exception is not handled by application code." 

Quindi: solo l’ eccezione non gestita sarà disponibile nel gestore eventi OnException. Quello che stai vivendo è probabilmente l’IDE Delphi che si rompe sull’eccezione. Questo è (almeno in Delphi 7) configurabile.

In Delphi 7 puoi configurarlo facendo clic sul menu Strumenti-> Opzioni debugger. Quindi selezionare “Eccezioni di lingua” un un-ckech la casella di controllo “Eccezioni Stop su Delphi”. Potrebbe tuttavia essere diverso in altre versioni di Delphi.

Un’alternativa potrebbe essere quella di non utilizzare Application.OnException. Ma per catturare semplicemente tutte le eccezioni nella tua funzione “principale”. In questo modo puoi catturare tutte le eccezioni che non hai memorizzato nella cache prima, registrare l’eccezione e poi andare in crash.

Application.OnException dovrebbe sparare solo per eccezioni non gestite. Rialzare un’eccezione in un blocco try-except farà sì che l’eccezione venga gestita da Application.OnException. Per la convalida dell’input che genera un’eccezione, è ansible visualizzare un messaggio all’utente e quindi sollevare nuovamente l’eccezione solo se si desidera che venga registrata nel log degli errori.