2014-12-03 8 views
5

Ho appena scavato un bug nel codice stiamo lavorando con * che stava venendo a mancare a causa della seguente situazione:Chiamata di funzione all'interno assert == male?

Assert(SomeVitalFunction(foo) == OK) 

Questo ha funzionato bene per tutto il tempo le macro DEBUG stati #defined:

#ifdef DEBUG 
    #define Assert(x) if((x) == 0){/*some error handling*/} 
#else 
    #define Assert(x) 
#endif 

Ma quando abbiamo #undef'd DEBUG ha l'effetto di eliminare la chiamata di funzione vitale dal codice.

Non riesco a capire come potrebbe funzionare con DEBUG #undef 'd, e sembra una cattiva idea in generale mettere qualsiasi tipo di chiamata di funzione all'interno di un asser come questo.

Ho perso qualcosa?

* = Modifica per chiarire seguente commento di Carpetsmoker: Il codice viene da una cabala particolarmente arretrata di schiavi codice Elbonian, il nostro compito è stato quello di incidere, tagliare, la barba, polacco, disinfettare e applicare il rossetto alla cosa.

+3

Il punto di "assert' è di" * aiutare i programmatori a trovare bug nei loro programmi * "... Quindi tutti gli asert dovrebbero idealmente essere rimovibili, e tutto dovrebbe funzionare ugualmente. Quindi hai ragione nella tua osservazione e tu o uno dei tuoi colleghi avete fatto un errore in passato. – Carpetsmoker

+0

Ho scritto una macro di Visual Studio molto tempo fa per cercare la base di codice per questo (in quei giorni, cercando 'ASSERT (... (...)' - cioè 2 o più parentesi prima di quella di chiusura) perché è un problema così grande quando succede. – AAT

risposta

5

Non ti è mancato nulla.

Gli avvisi devono sempre essere scritti come se potessero scomparire con il semplice tocco di un interruttore del compilatore.

può chiamare funzioni che richiedono un tempo relativamente lungo per completare all'interno di un assert (ad esempio l'analisi dell'integrità di una struttura di dati), perché la chiamata di funzione non sarà presente nella versione di rilascio. Il rovescio della medaglia è che tu non puoi funzioni di chiamata necessarie per il corretto funzionamento.

2

Dipende da cosa sta facendo SomeVitalFunction. Se non ha effetti collaterali interessanti , è ok usarlo all'interno di uno assert. Ma se chiamare o non chiamare SomeVitalFunction è essenziale per il programma, è un bug.

Ad esempio, su POSIX, kill(2) con un segnale 0 è utile solo per verificare se un processo è in corso. Immagino che si potrebbe essere a volte tentati di usare

assert(kill(sompid, 0) == 0); // process sompid exists 

supponendo che si supponga sempre che il processo sompid è ancora in esecuzione.

Allo stesso modo, è possibile utilizzare assert(hash_table_count(htbl)>0); per verificare che una tabella hash htbl non sia vuota.

proposito, si noti che è assert(3)documentato come essere ignorato se si compila con l'opzione -DNDEBUG preprocessore (non se -DDEBUG non è dato).

Problemi correlati