2010-04-15 4 views
8

Inoltre, come si può paragonare al lancio di un'eccezione quando qualcosa va storto?VERIFY (...) è una buona pratica nella codifica C++?

+2

Err .. che cos'è VERIFY()? Non è nella libreria standard C++ ... intendi una dichiarazione di affermazione? –

+0

Sembra essere correlato a MFC: http://msdn.microsoft.com/en-us/library/fcatwy09(VS.71).aspx – Amber

+1

Mi chiedo perché la libreria standard ha assunto() ma non verifica() – Inverse

risposta

18

VERIFY() serve allo stesso scopo come ASSERT() (o la libreria standard assert()) - che consente di catturare le cose che in realtà non dovrebbe mai accadere (cioè un codice di vero bug, qualcosa che dovrebbe essere risolto prima del rilascio) . Il genere di cose che se per qualche ragione l'espressione è falsa, non ha senso continuare perché qualcosa è orribilmente, orribilmente sbagliato.

Ciò si riflette nel fatto che VERIFY() interrompe il programma solo su una valutazione errata durante la compilazione in modalità Debug: in modalità di rilascio, è trasparente. La differenza tra VERIFY() e ASSERT() è che VERIFY() valuterà comunque l'espressione in modalità Rilascio, semplicemente non si preoccuperà del risultato - mentre ASSERT() viene completamente rimosso dal programma durante la compilazione in modalità di rilascio e quindi qualsiasi effetto collaterale dell'espressione al suo interno non avrà luogo.

Le eccezioni sono più utili per le cose che potrebbero essere errate, ma possono essere ripristinate da, poiché le eccezioni possono essere gestite da altre parti del programma.

5

In Visual C++ sono disponibili due macro per il controllo delle condizioni: ASSERT e VERIFY.

In modalità di debug, entrambi si comportano allo stesso modo: vale a dire, entrambi valutano il loro argomenment e se il risultato è 0, entrambi bloccano il programma con una finestra di dialogo di errore dell'asserzione.

La differenza sta nella modalità di rilascio. Nella modalità di rilascio, ASSERT è completamente rimosso dal programma: non valuta affatto l'espressione. VERIFY, d'altra parte, valuta ancora l'espressione, ignora semplicemente il risultato.

Personalmente, il mio parere è che se il controllo è valido in modalità di debug, allora è comunque valido anche in modalità di rilascio e probabilmente non si dovrebbe usare nessuno dei due. Basta fare il test e lanciare un'eccezione (o utilizzare una macro personalizzata che si espande in assert() in modalità di debug e un'eccezione nella modalità di rilascio).

+1

Una differenza utile è che se si hanno test "nitpicky" che richiedono un po 'di tempo per essere eseguiti, è possibile inserirli in un 'ASSERT()' e quindi non preoccuparsi delle perdite di prestazioni in modalità Release. – Amber

+0

Anche in questo caso il controllo della modalità di debug in modalità di rilascio è ben supportato! – Cameron

6

La domanda sembra semplice, ma nasconde un argomento enorme: affrontare gli errori.

Summarilly direi assert e verificare sono strumenti da utilizzare nel processo di sviluppo mentre eccezioni e chiamate di sistema di controllo degli errori sono parti normali di codice di produzione per affrontare errori di runtime.

  • asserzioni (si applica per affermare e verificare) sono gli strumenti più utilizzati in stile di programmazione difensiva. Il loro obiettivo principale è di proteggere da casi che non dovrebbero mai accadere e il programmatore non ha idea di cosa fare se ciò dovesse accadere. Di solito è usato per verificare errori di programmazione. Quando l'impossibile si verifica durante il debug di un programma, di solito lo si vuole rilevare e segnalarlo il più velocemente possibile. Semplifica la correzione degli errori. Puoi usarlo con alcune condizioni o addirittura come assert(false) in genere per verificare che un ramo di un interruttore non venga mai catturato.

    Principalmente uso affermazioni quando si tratta di codice di terze parti il ​​cui comportamento non è sicuro. Per il controllo del comportamento del mio codice in fase di sviluppo, di solito preferisco test delle unità.

    Ora, come ci ha insegnato Schroëdinger, le misure cambiano le cose. A volte è possibile che il codice funzioni in modalità di debug quando l'assert è abilitato e smette di funzionare in modalità di rilascio. Di solito è il sintomo di un bug nascosto all'interno della condizione di asserzione (effetto collaterale, codice sensibile al tempo). Verificare minimizzare questo tipo di rischio, ma può essere considerato una cattiva pratica, come spazzare polvere dietro il tappeto.

    È inoltre possibile utilizzare verificare per la codifica rapida come scafolding per i punti in cui non è stato ancora impostato un vero errore di gestione. Non credo che dovresti consentire alcuna verifica nel codice di produzione.

  • eccezioni sono una parte normale di flusso di controllo del programma. Molto spesso sono abituati ad affrontare errori, ma non è il loro unico uso possibile (quelli che usano altri linguaggi come Python sapranno di cosa sto parlando). Né dovrebbero essere considerati come l'unico strumento di gestione degli errori. Quando non sono racchiusi in una libreria C++, le chiamate di sistema restituiscono ancora un codice di errore invece di generare un'eccezione.

    Come regola generale, le eccezioni devono essere catturate dall'oggetto più vicino che sia in grado di gestirle in modo ragionevole.

    Inoltre, non tutte le eccezioni devono essere considerate come errori irreversibili e arresto del programma. Immagina di avere a che fare con una libreria di streaming video di rete restituendo casi di errore tramite eccezioni. La libreria lancia un avviso di eccezione che indica che un frame è stato rilasciato, di solito non si desidera arrestare il programma ma solo prepararlo per il fotogramma successivo.

    Anche quando la cosa migliore da fare è arrestare il programma, non dovresti lasciare che l'eccezione lo faccia per te (e hai ancora meno motivi per usare l'asserzione per quello scopo nel codice di produzione). Ci dovrebbe sempre esistere un gestore di eccezioni di primo livello a tale scopo che faccia chiamate esplicite a exit() di like. Non farlo mostra semplicemente che il programmatore non si è preoccupato di cosa potrebbe accadere e probabilmente non ci ha pensato.

+0

Good point, +1 ... – sevaxx

+3

L'inserimento in un gestore di eccezioni di primo livello per "eccezioni non rilevate" ha lo svantaggio che quando si verifica un'eccezione non rilevata, lo stack viene distrutto fino al gestore di livello superiore; che poi farà qualcosa di completamente disinteressato come dire che si è verificata un'eccezione, quindi come dici tu, esci comunque dal programma. Lasciandolo completamente non gestito offre al debugger l'opportunità di interrompere il programma allo std :: terminare con l'intero stack di esecuzione disponibile e ispezionabile. – rvalue