2012-05-21 10 views
7

Sto rifattorizzando un vecchio codice e una delle cose che vorrei risolvere è il modo in cui vengono gestiti gli errori. Sono ben consapevole delle eccezioni e del loro funzionamento, ma non sono del tutto sicuro che siano la soluzione migliore per le situazioni che sto cercando di gestire.Come terminare un programma C++ dopo un errore?

In questo codice, se le cose non convalidano, non c'è davvero alcun motivo o vantaggio per srotolare lo stack. Sono state fatte. Non ha senso cercare di salvare la nave, perché si tratta di un codice non interattivo che viene eseguito in parallelo attraverso il motore Sun Grid. L'utente non può intervenire. Inoltre, questi fallimenti di validazione non rappresentano davvero circostanze eccezionali. Sono attesi.

Quindi, come faccio a gestire meglio questo? Una cosa che non sono sicuro di volere è un punto di uscita in ogni metodo di classe che può fallire. Ciò sembra irrinunciabile. Ho sbagliato? È pratica accettabile chiamare semplicemente exit() o abort() nel punto di errore in codici come questo? O dovrei lanciare un'eccezione fino ad una dichiarazione di cattura generica in main? Qual è il vantaggio?

+0

C'è qualche buono da recuperare da un'eccezione o vuoi semplicemente uscire quando si verifica un errore? Non è un po 'troppo quando la tua applicazione si blocca ogni volta che si verifica un errore? – DumbCoder

+0

Sto usando eccezioni e simili per problemi non fatali. Sto davvero cercando di risolvere la situazione di errore fatale qui. – Fadecomic

risposta

4

Lanciare un'eccezione da catturare in main e quindi uscire significa che gli oggetti delle risorse RAII vengono ripuliti. Sulla maggior parte dei sistemi questo non è necessario per molti tipi di risorse. Il SO pulirà la memoria, i manici dei file, ecc.(anche se ho usato un sistema in cui non riuscendo a liberare memoria significava che rimaneva assegnato fino al riavvio del sistema, quindi perdite all'uscita del programma non erano una buona idea.)

Ma ci sono altri tipi di risorse che potresti voler rilasciare in modo pulito come le connessioni di rete o di database o un dispositivo meccanico che stai guidando e che devono essere arrestati in modo sicuro. Se un'applicazione utilizza molte di queste cose, potresti preferire lanciare un'eccezione per ricollocare lo stack su main, e quindi uscire.

Quindi il metodo appropriato per uscire dipende dall'applicazione. Se un'applicazione sa che è sicura, chiamare _Exit(), abort(), exit() o quickexit() può essere perfettamente ragionevole. (Il codice della libreria non dovrebbe chiamarli, dal momento che ovviamente la libreria non ha idea se sia sicuro per ogni applicazione che utilizzerà mai la libreria.) Se è necessario eseguire una pulizia critica prima che un'applicazione esca ma si sa che è limitata , quindi l'applicazione può registrare quel codice di pulizia tramite atexit() o at_quick_exit().

Quindi, in pratica, decidi cosa è necessario ripulire, documentarlo, implementarlo e provare a verificare che sia testato.

2

io suggerirei di chiamare funzione globale

void stopProgram() { 
    exit(1); 
} 

In seguito è possibile modificare il suo comportamento, quindi è gestibile.

+0

È 'void exit (int status)', non 'void exit()'. – Griwes

+0

@Griwes: Grazie, aggiornato –

1

Come hai sottolineato, avere un exit o abort gettato in giro per tutto il codice non è gestibile ... inoltre, potrebbe esserci un meccanismo in futuro che potrebbe consentire di recuperare da un errore, o gestire un errore in un modo più aggraziato del semplice esiting, e se hai già codificato questa funzionalità, allora sarebbe molto difficile da annullare.

Lanciare un'eccezione catturata in main() è la soluzione migliore a questo punto che offrirà anche flessibilità in futuro se si esegue il codice in uno scenario diverso che consentirà di recuperare dagli errori o gestirli in modo diverso. Inoltre, il lancio di eccezioni potrebbe aiutare nel caso decidessi di aggiungere più supporto per il debug, ecc., Poiché ti darà punti per implementare le funzionalità di registrazione e registrare lo stato del programma da punti isolati e manutenibili nel software prima di decidere di far uscire il programma.

4

È possibile terminare il programma se non è in grado di gestire l'errore con garbo. Ci sono alcune cose che puoi fare:

  • Chiama abort() se hai bisogno di un core dump.
  • Chiamare exit() se si vuole dare la possibilità di eseguire le routine registrate con atexit() (che è più probabile chiamare i distruttori per oggetti C++ globali).
  • Chiamare _exit() per terminare immediatamente un processo.

Non c'è niente di sbagliato nell'usare queste funzioni finché capisci quello che stai facendo, conosci le tue altre scelte e scegli quel percorso volentieri. Dopotutto, è per questo che esistono quelle funzioni. Quindi se non pensi che abbia senso provare a gestire l'errore o fare qualsiasi altra cosa quando succede - vai avanti. Quello che probabilmente farei è provare a registrare un messaggio informativo (per esempio, su syslog) e chiamare _exit. Se la registrazione non riesce, chiamare abort per ottenere un nucleo lungo la terminazione.

Problemi correlati