Condividi tramite


Errori e gestione delle eccezioni C++ (moderno)

In C++ moderno, nella maggior parte dei casi, il modo migliore per segnalare e gestire gli errori di runtime e gli errori di logica consiste nell'utilizzare le eccezioni.Ciò vale soprattutto quando lo stack può contenere diverse chiamate di funzione tra la funzione che consente di rilevare l'errore e la funzione che ha il contesto di imparare a gestirlo.Eccezioni forniscono un metodo formale, ben definito per il codice che consente di rilevare gli errori per passare le informazioni allo stack di chiamate.

Gli errori di programma sono divisi in due categorie: errori di logica che sono causati da errori, di programmazione, ad esempio, un errore "indice esterno all'intervallo" e gli errori di runtime sono imputabili al programmatore, ad esempio, un errore di "servizio non disponibile" rete".In programmazione in stile c e COM, segnalazione errori viene gestito tramite la restituzione di un valore che rappresenta un codice di errore o un codice di stato per una determinata funzione o impostando una variabile globale che il chiamante può recuperarle dopo ogni chiamata di funzione per verificare se sono stati segnalati errori.Ad esempio, programmazione COM utilizza il valore restituito HRESULT per comunicare gli errori al chiamante e l'API Win32 ha la funzione GetLastError per recuperare l'ultimo errore è stato segnalato dallo stack di chiamate.In entrambi i casi, spetta al chiamante di riconoscere il codice e di rispondere in modo appropriato.Se il chiamante non in grado di gestire in modo esplicito il codice di errore, il programma potrebbe bloccarsi senza alcun avviso o continuare a eseguire con dati non validi e produrre risultati non corretti.

Le eccezioni sono preferite in C++ moderno per i seguenti motivi:

  • Un'eccezione impone il codice chiamante di riconoscere una condizione di errore e di gestirlo.Le eccezioni non gestite interrompono l'esecuzione del programma.

  • Un'eccezione si sposterà il punto nello stack di chiamate in grado di gestire l'errore.Funzioni intermedie possono consentire l'eccezione di propagazione.Non è necessario coordinare con altri livelli.

  • Il meccanismo di rimozione dello stack eccezione Elimina tutti gli oggetti nell'ambito in base alle regole ben definite dopo un'eccezione.

  • Un'eccezione consente una chiara separazione tra il codice che rileva l'errore e il codice che gestisce l'errore.

Nell'esempio semplificato viene illustrata la sintassi necessaria per la generazione e intercettazione di eccezioni C++.

 
#include <stdexcept>
#include <limits>
#include <iostream>
 
using namespace std;
class MyClass
{
public:
   void MyFunc(char c)
   {
      if(c < numeric_limits<char>::max())
         throw invalid_argument("MyFunc argument too large.");
      //...
   }
};

int main()
{
   try
   {
      MyFunc(256); //oops!
   }
 
   catch(invalid_argument& e)
   {
      cerr << e.what() << endl;
      return -1;
   }
   //...
   return 0;
}

Le eccezioni C++ sono simili a quelle in linguaggi quali c# e Java.Nel try blocco, se è un'eccezione generata un'eccezione sarà catturati per il primo associati catch blocco cui tipo corrisponde a quello dell'eccezione.In altre parole, l'esecuzione passa dal throw istruzione per la catch istruzione.Se non viene rilevato alcun blocco catch utilizzabile, std::terminate viene richiamato e il programma si chiude.In C++, è possibile che venga generato qualsiasi tipo; Tuttavia, si consiglia la generazione di un tipo che deriva direttamente o indirettamente da std::exception.Nell'esempio precedente, il tipo di eccezione, invalid_argument, definita nella libreria standard del <stdexcept> file di intestazione.C++ non è disponibile e non richiede un finally blocco per assicurarsi che tutte le risorse vengano rilasciate se viene generata un'eccezione.L'acquisizione di risorse è il linguaggio di inizializzazione (RAII), che utilizza puntatori intelligenti, fornisce le funzionalità necessarie per la pulitura delle risorse.Per ulteriori informazioni, vedere Procedura: Progettazione di sicurezza di eccezione.Per informazioni sul meccanismo di rimozione dello stack C++, vedere Eccezioni e rimozione dello stack in C++.

Linee guida di base

La gestione degli errori affidabile è problematico in qualsiasi linguaggio di programmazione.Anche se le eccezioni sono disponibili diverse funzionalità che supportano la gestione degli errori buona, essi non tutto il lavoro.Per ottenere i vantaggi del meccanismo di eccezione, tenere presenti le eccezioni durante la progettazione del codice.

  • Utilizzare le asserzioni per controllare gli errori non dovrebbero mai verificarsi.Utilizzare le eccezioni per controllare gli errori che potrebbero verificarsi, ad esempio, gli errori di convalida dell'input per i parametri delle funzioni pubbliche.Per ulteriori informazioni, vedere Exceptions VS. Assertions.

  • Utilizzare le eccezioni quando il codice che gestisce l'errore potrebbe essere separato dal codice che rileva l'errore da uno o più chiamate di funzione intermedi.Valutare l'ipotesi di utilizzare i codici di errore nei cicli prestazioni critici quando il codice che gestisce l'errore è strettamente collegata al codice che rileva.Per ulteriori informazioni su quando non si desidera utilizzare le eccezioni, vedere When Not to Use Exceptions.

  • Per ogni funzione che potrebbe generare un'eccezione di propagazione, costituiscono una delle garanzie tre eccezioni: la garanzia sicura, la garanzia di base o la garanzia di nothrow (noexcept).Per ulteriori informazioni, vedere Procedura: Progettazione di sicurezza di eccezione.

  • Generare eccezioni in base al valore, li rileverà per riferimento.Non si rilevano non può gestire.Per ulteriori informazioni, vedere Linee guida per la generazione e intercettare le eccezioni (C++).

  • Non utilizzare specifiche di eccezione, che sono obsoleti in C + + 11.Per ulteriori informazioni, vedere Exception specifications and noexcept.

  • Utilizzare i tipi di eccezione di libreria standard quando si applicano.Derivare da tipi di eccezioni personalizzate il eccezione classe gerarchia.Per ulteriori informazioni, vedere Procedura: Utilizzare gli oggetti eccezione standard di libreria.

  • Non consentire eccezioni uscire dalla distruttori o funzioni della deallocazione di memoria.

Le eccezioni e prestazioni

Il meccanismo delle eccezioni è delle prestazioni ridotto al minimo il costo viene generata alcuna eccezione.Se viene generata un'eccezione, il costo dell'attraversamento dello stack e la rimozione è approssimativamente paragonabile al costo di una chiamata di funzione.Strutture di dati aggiuntive sono necessarie per tenere traccia dello stack di chiamate dopo un try blocco e ulteriori istruzioni sono necessari per la rimozione dello stack, se viene generata un'eccezione.Nella maggior parte dei casi, tuttavia, il costo delle prestazioni e footprint di memoria non è significativo.L'effetto negativo delle eccezioni sulle prestazioni è probabile che sia significativo solo nei sistemi molto limitata di memoria o in prestazioni critiche ciclo in cui è probabile che si verificano regolarmente un errore e il codice per gestire il file è strettamente collegato al codice che segnala.In ogni caso, è possibile conoscere il costo effettivo delle eccezioni senza analisi e la misurazione.Anche nei casi rari quando il costo sia significativo, è possibile pesare contro la correttezza di un aumento, facilità di gestione più semplice e altri vantaggi forniti da un criterio di eccezione ben progettato.

Eccezioni VS. asserzioni

Le eccezioni e le asserzioni sono due distinti meccanismi per il rilevamento di errori di run-time in un programma.Utilizzare le asserzioni per verificare le condizioni durante lo sviluppo, che non dovrà mai essere true se tutto il codice è corretto.Nessun punto nella gestione di un errore con un'eccezione in quanto l'errore indica che un elemento nel codice è fissato e non rappresenta una condizione che il programma dispone per il ripristino da in fase di esecuzione.Un'asserzione interrompe l'esecuzione in corrispondenza dell'istruzione in modo che è possibile controllare lo stato del programma nel debugger; un'eccezione continua l'esecuzione dal primo gestore catch appropriata.Utilizzare le eccezioni per verificare le condizioni di errore che potrebbero verificarsi in fase di esecuzione, anche se il codice è corretto, ad esempio, "file non trovato" o "memoria esaurita." È possibile ripristinare queste condizioni, anche se il ripristino solo genera un messaggio a un registro e la chiusura del programma.Controllare sempre gli argomenti alle funzioni pubbliche utilizzando le eccezioni.Anche se la funzione è esente da errori, non è possibile controllo completo di argomenti che un utente potrebbe passare.

Eccezioni C++ e le eccezioni SEH di Windows

Programmi c e C++ è possono utilizzare il meccanismo (SEH) nel sistema operativo Windows di gestione strutturata delle eccezioni.I concetti di SEH simili a quelle di eccezioni C++, ad eccezione del fatto che utilizza SEH di __try, __except, e __finally costruisce invece di try e catch.In Visual C++, le eccezioni C++ vengono implementate per SEH.Tuttavia, quando si scrive codice C++, utilizzare la sintassi di eccezione C++.

Per ulteriori informazioni su SEH, vedere Gestione delle eccezioni strutturata (C++).

Noexcept e specifiche di eccezione

Specifiche di eccezione sono stati introdotti in C++ consente di specificare le eccezioni che può generare una funzione.Tuttavia, si è dimostrato problematiche in pratica specifiche di eccezione e sono obsolete in C + + 11 bozza standard.Si consiglia di non utilizzare specifiche di eccezione, ad eccezione di throw(), che indica che l'eccezione non consente di consentire eccezioni di escape.Se è necessario utilizzare specifiche delle eccezioni del tipo throw(tipo), tenere presente che Visual C++ è diversa da standard in determinati modi.Per ulteriori informazioni, vedere Specifiche di eccezione.Il noexcept identificatore viene introdotto in C + + 11 come migliore alternativa a throw().

Vedere anche

Concetti

Procedura: Interfaccia tra il codice eccezionale e Non Eccezionale

Altre risorse

Digitare di nuovo a C++ (C++ moderno)

Riferimenti al linguaggio C++

Riferimento della libreria C++ standard