Domanda

In C++, sto cercando di catturare tutti i tipi di eccezioni in un'unica cattura (come catch(Exception) in C#).Com'è fatto?E soprattutto, come si possono individuare le eccezioni di divisione per zero?

È stato utile?

Soluzione

catch (...)
{
   // Handle exceptions not covered.
}

Considerazioni importanti:

  • Un approccio migliore consiste nel rilevare tipi specifici di eccezioni da cui è possibile effettivamente recuperare anziché tutte le possibili eccezioni.
  • catch(...) rileverà anche alcune eccezioni gravi a livello di sistema (varia a seconda del compilatore) da cui non sarai in grado di recuperare in modo affidabile.Catturarli in questo modo, poi ingoiarli e continuare potrebbe causare ulteriori seri problemi al tuo programma.
  • A seconda del contesto può essere accettabile utilizzare catch(...), a condizione che l'eccezione venga nuovamente lanciata.In questo caso, si registrano tutte le informazioni utili sullo stato locale e quindi si lancia nuovamente l'eccezione per consentirne la propagazione.Comunque dovresti documentarti su Modello RAII se scegli questo percorso

Altri suggerimenti

Voi non voglio usare catch (...) (i.e.catturare con i puntini di sospensione) a meno che tu non ne abbia davvero, sicuramente, e in modo dimostrabile, bisogno.

La ragione di ciò è che alcuni compilatori (Visual C++ 6 per citare i più comuni) trasformano anche errori come errori di segmentazione e altre condizioni davvero pessime in eccezioni che puoi gestire volentieri utilizzando catch (...).Questo è molto brutto, perché non vedi più gli arresti anomali.

E tecnicamente, sì, puoi anche catturare la divisione per zero (dovrai "StackOverflow" per questo), ma in primo luogo dovresti evitare di fare tali divisioni.

Invece, procedi come segue:

  • Se sai effettivamente che tipo di eccezioni aspettarti, cattura quei tipi e non altro, e
  • Se hai bisogno di lanciare eccezioni tu stesso e devi catturare tutte le eccezioni che lancerai, fai in modo che queste eccezioni derivino da std::exception (come suggerito da Adam Pierce) e catturalo.

Se utilizzi Windows e devi gestire errori come la divisione per zero e la violazione di accesso, puoi utilizzare un traduttore di eccezioni strutturato.E poi all'interno del tuo traduttore puoi lanciare un'eccezione C++:

void myTranslator(unsigned code, EXCEPTION_POINTERS*)
{
    throw std::exception(<appropriate string here>);
}

_set_se_translator(myTranslator);

Nota, il codice ti dirà qual era l'errore.Inoltre è necessario compilare con l'opzione /EHa (C/C++ -> Code Generatrion -> Abilita eccezioni C/C++ = Sì con eccezioni SEH).

Se ciò non ha senso controlla i documenti per [_set_se_translator](http://msdn.microsoft.com/en-us/library/5z4bw5h5(VS.80).aspx)

Se catturare tutte le eccezioni, comprese quelle del sistema operativo, è davvero ciò di cui hai bisogno, devi dare un'occhiata al tuo compilatore e al tuo sistema operativo.Ad esempio, su Windows probabilmente hai la parola chiave "__try" o l'opzione del compilatore per fare in modo che "try/catch" catturi le eccezioni SEH o entrambi.

Fai in modo che tutte le tue classi di eccezioni personalizzate ereditino da std::exception, quindi puoi semplicemente catturare std::exception.Ecco qualche esempio di codice:

class WidgetError
    : public std::exception
{
public:
    WidgetError()
    { }

    virtual ~WidgetError() throw()
    { }

    virtual const char *what() const throw()
    {
        return "You got you a widget error!";
    }
};

In C++, lo standard non definisce un'eccezione di divisione per zero e le implementazioni tendono a non lanciarla.

Puoi, ovviamente, usare catch (...) { /* code here */ }, ma dipende davvero da cosa vuoi fare.In C++ hai distruttori deterministici (nessuna di quelle sciocchezze di finalizzazione), quindi se vuoi ripulire, la cosa corretta da fare è usare RAII.

Per esempio.invece di:

void myfunc()
{
    void* h = get_handle_that_must_be_released();
    try { random_func(h); }
    catch (...) { release_object(h); throw; }
    release_object(h);

}

Fai qualcosa del tipo:

#include<boost/shared_ptr.hpp>

void my_func()
{
    boost::shared_ptr<void> h(get_handle_that_must_be_released(), release_object);
    random_func(h.get());
}

Crea la tua classe con un distruttore se non usi boost.

Se ricordo bene (è passato un po' di tempo dall'ultima volta che ho guardato il C++), penso che quanto segue dovrebbe fare al caso mio

try
{
 // some code
}
catch(...)
{
 // catch anything
}

e una rapida ricerca su Google(http://www.oreillynet.com/pub/a/network/2003/05/05/cpluspocketref.html) sembra darmi ragione.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top