Domanda

asserzione viene utilizzato per verificare se una condizione è soddisfatta (precondizione, postcondition, invarianti) e aiutare i programmatori di trovare buchi durante la fase di debug.

Ad esempio,

void f(int *p)
{
  assert(p);
  p->do();
}

La mia domanda è abbiamo bisogno di assumere la condizione non poteva essere soddisfatta nella modalità di rilascio e gestire il caso di conseguenza?

void f(int *p)
{
  assert(p);

  if (p)
  {
    p->do();
  }
}

Dopo tutto, mezzi affermazione che la condizione si verifica dovrebbe mai essere falso. Ma se, se non controlliamo e non riesce, il programma si blocca. Suona come un dilemma. Come fate a che fare con esso?

È stato utile?

Soluzione

Se l'asserzione fallisce, il programma dovrebbe bloccarsi .

un'affermazione mancanza di mezzi il programmatore ha fatto un errore fondamentale nella loro comprensione di come sia possibile per il flusso del programma di procedere. Si tratta di un aiuto allo sviluppo, non un aiuto alla produzione. Nella produzione, si potrebbe gestire eccezioni , in quanto "potrebbe" accadere, mentre le affermazioni devono "mai" fallire.

Se siete nel campo che dice: "Oh, ma cosa succede se le affermazioni non riescono in produzione? Ho bisogno di prenderli!" allora vi state perdendo il punto. Chiedete a voi stessi, in tal caso, perché non stai solo un'eccezione (o in altro modo la gestione dell'errore)?

In linea generale, assert è non solo una scorciatoia per "Se la condizione non è soddisfatta, tranne due" (bene, a volte questa è la semantica operazionale, ma non è il denotazionale semantica). Piuttosto, un'affermazione in mancanza di mezzi l'applicazione è in uno stato lo sviluppatore non crede è nemmeno possibile . Vuoi davvero il codice per continuare l'esecuzione in tal caso di un? Chiaramente (direi), No .

Altri suggerimenti

programmazione difensiva è sempre meglio. Si deve sempre pensare che, nonostante tutto il test, l'applicazione sarà disponibile con gli insetti. Come tale, è nel vostro interesse per aggiungere controlli NULL in situazioni in cui è possibile evitare una deferenza puntatore NULL e semplicemente andare avanti.

Tuttavia, vi sono situazioni in cui non c'è semplicemente modo non semplice per evitare un incidente, e in quei casi, l'asserzione è il vostro unico modo di rilevare il problema durante il ciclo di sviluppo.

Un punto importante però - afferma vengono spesso utilizzati per rilevare i principali problemi con l'integrità dei dati. Se si continua passato quelli afferma, si potrebbe rischiare di danneggiare i dati. In questi casi, può essere meglio di crash piuttosto che distruggere i dati. (Ovviamente, qualsiasi tipo di gestore di crash che almeno richiama una ragionevole UI con una descrizione dell'errore sarebbe preferibile).

A rigor di termini, il secondo codice ha la ridondanza.

void f(int *p)
{
  assert(p);
  if (p)    // Beats the purpose of assertion
  {
    p->do();
  }
}

Si è verificato asserzione errore mezzi. Qualcosa che è inaspettato / non gestite. Nel codice di cui sopra, sia

1) si gestisce correttamente il caso in cui p è nullo. (Da non chiamare p-> do ()) - che si suppone sia il diritto / cosa dovrebbe fare. Tuttavia, allora l'asserzione è un falso allarme .

2) D'altra parte, se non chiamando p-> do (), qualcosa vada storto (forse ulteriormente nel codice o in uscita), quindi l'affermazione è giusta, ma ci dovrebbe essere alcun senso continuando comunque.

Nel codice sopra il programmatore sta lavorando duramente per casi manico che sono errate in ogni modo.

Detto questo, alcune persone come per trattare afferma come qualcosa ha sbagliato andato, ma vediamo se abbiamo ancora ottenere l'output corretto . IMO, che è cattiva strategia e crea confusioni durante la correzione di bug.

affermazioni sono il debug del codice, non funziona il codice. Non utilizzarli per errori di input di cattura.

Le asserzioni sono utilizzati per i bug di cattura in fase di test. La teoria è che hai provato abbastanza bene da sapere che funziona una volta che hai rilasciato.

Se non c'è alcuna possibilità che la condizione potrebbe sorgere nel funzionamento vita reale, non si basano su affermazioni -. Utilizzare le eccezioni o qualche altro meccanismo errore

asserisce sono utili per il debug come lei ha ricordato. Non dovrebbero mai fare in codice di produzione (come compilato, è ok per avvolgerli in #ifdefs ovviamente)

Se si sta eseguendo in un problema in cui è oltre il controllo di rettificare ed è necessario il controllo nel codice di produzione mi piacerebbe fare qualcosa di simile:

void f(int *p)
{

  if (!p)
  {
    do_error("FATAL, P is null.");
  }

  p->do();
}

Dove do_error è una funzione che registra un errore ed esce pulita.

dico lasciarli dentro in una build di rilascio. Ci sono tenuti ad essere di problemi di qualsiasi costruzione. Avendo afferma nel vostro mezzo prodotto è possibile individuare il problema più facilmente quando si riceve un report problema da un Uwer.

Non mettere molto impegno nel gestire le eccezioni. Semplicemente assicurarsi la possibilità di entrare in possesso della deroga completa, includigg stacktrace. Applicabile a un build di rilascio in particolare.

Dal momento che molte persone stanno commentando mettere affermazioni nella modalità di rilascio:

In che io lavoro su, l'efficienza è molto importante (a volte, l'esecuzione su grandi insiemi di dati richiede decine di ore a pochi giorni per essere completato). Quindi, abbiamo macro speciali che affermano solo nel codice di debug (eseguito durante QA, ecc). A titolo di esempio, un'asserzione all'interno di un ciclo for è sicuramente un testa e si consiglia di evitarlo in codice di rilascio. Dopo tutto, se tutto iz bene, afferma non è dovuto a fallire.

Un esempio in cui il codice di rilascio asserisce sono buone è - se la logica non dovrebbe colpire un ramo particolare di codice a tutti. In questo caso, assert (0) è soddisfacente [così qualsiasi tipo di assert (0) può sempre essere lasciato nel codice rilascio].

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