2013-01-11 5 views
6

Durante la programmazione sto usando assert e convalida del puntatore NULL.Uso della convalida Assert e del puntatore NULL cosa è meglio usare

Ma come so assert sarà utile solo nella modalità DEBUG.

La mia domanda è Supponiamo che io sono un puntatore interno che io sono sicuro che posso essere funzione di esempio NULL restituisce un puntatore (ma il puntatore non è un membro della classe) in questi casi posso usare assert

test* ptr = fun(); // return a pointer of type test 
assert(ptr); 

//do some operation 

o NULL pointer convalida

test* ptr = fun(); // return a pointer of type test 
assert(ptr); 
if (NULL != ptr) 
{ 
    //do some operation 
} 

Ecco che pratica il codice è good.As per la mia sottovalutare sarà secondo. Perché ho dovuto affrontare alcune situazioni in cui il valore di ptr restituisce NULL a causa di alcuni casi anomali a cui non possiamo nemmeno pensare.

Ma abbiamo altre opzioni migliori?

+0

Perché questa domanda è votata come chiusa? È una domanda valida – Nawaz

+0

Hai considerato di non restituire nulla? Sarebbe molto più facile scrivere codice. Cioè array vuoti/speciali [oggetti null] (http://en.wikipedia.org/wiki/Null_Object_pattern) e le eccezioni possono limitare in modo significativo la necessità di restituire null e quindi di controllarlo. –

+0

@AlexeiLevenkov check secondo caso –

risposta

3

La soluzione reale dipende dalla semantica della funzione fun.

Se ritorno NULL è semanticamente valida, allora penso fun dovrebbe generare un'eccezione appropriato (come std::logic_error) invece di tornare NULL, e si potrebbe utilizzare assert sul sito chiamata a garantire che fun sta lavorando bene, e se non funziona bene, quindi interrompere il programma. In questo modo, il bug in fun non si propaga al resto del programma, poiché viene catturato immediatamente.

Tuttavia, se dovessi tornare NULL da fun è semanticamente valida, allora si dovrebbe verificare il valore restituito sulla chiamata in loco utilizzando if e assert non è realmente necessario in questo caso, perché si utilizzerà if comunque.

1. Oppure è possibile utilizzare std::runtime_error o std::domain_error.

+0

alcuni scenari anormali possono rendere il valore restituito da ** fun ** come NULL o danneggiamento della memoria per quella variabile. Anche alcuni altri thread. Che significa finalmente per costringermi ad usare il secondo caso ... –

0

Come hai detto, asserisci solo durante il debug, aiutando il programmatore a identificare dove è andato male. Non ha alcun valore in produzione e quindi, preferisco usare il secondo metodo se hai qualche dubbio che il puntatore potrebbe essere NULL.

+0

sì preferisco il secondo metodo .... ma fun() non può idealmente restituire NULL. Quindi non è un controllo di condizioni extra o giochi sempre più sicuri con il lato sicuro :-) –

+1

Ma se hai l'asserzione in debug non testerai mai il percorso del codice dove il puntatore è nullo. Ciò significa che se dovesse accadere in produzione, i successivi percorsi di codice non saranno mai stati testati con il puntatore nullo e l'errore originale potrebbe essere mascherato dalla successiva esecuzione del codice. La successiva esecuzione del codice può o non può riprendersi dall'errore - questo fatto non può mai essere stato testato. –

+0

@CharlesBailey non sospetto che il valore del puntatore sia NULL mai. –

1

Ti consiglio di utilizzare il tuo codice per l'asserzione. come hai detto, asserire funziona solo in modalità di debug.

Quindi, se funziona in modalità di rilascio, non funziona.

se si utilizza il proprio codice di asserzione. puoi semplicemente scoprire cosa è sbagliato.

test* ptr = fun(); // return a pointer of type test 
MyOwnAssert(ptr); 

void MyOwnAssert(void* pPointer) 
{ 
    if (NULL == pPointer) 
    abort(); 
}  
+0

nel codice sopra si controlla per NULL non asserire e penso che il codice sopra può essere semplificato utilizzando MACRO invece di una funzione –

+0

sì, certo. ma, qui non è questo il punto. – VariOov

4

assert dice: "Se questo non è vero, v'è un errore logico nel mio codice". Se stai inserendo il codice per gestire il fatto che il puntatore potrebbe essere nullo, allora è la chiamata assert che è ridondante. Dovresti invece aggiungere la registrazione e la gestione al caso 'else'.In questo modo la build di debug verrà eseguita nello stesso modo della build di rilascio, anche nel caso del puntatore nullo.

Se si intende realmente affermare e si deve interrompere un puntatore nullo, abilitare gli asserzioni nella build di rilascio o utilizzare un meccanismo di asserzione abilitato per la versione alternativa.

L'unico motivo per un'asserzione di debug-only è la verifica di un errore logico troppo costoso da realizzare nel codice di rilascio. Normalmente un controllo nullo per un puntatore non si adatta a questa categoria.

0

Ciò che si fa di affermazione è una scelta personale: è possibile utilizzare è in produzione, se si desidera.

Direi che l'utilizzo di assert() è migliore se si desidera individuare i propri errori in anticipo. Soprattutto se il fatto che si tratta di un puntatore NULL non dovrebbe accadere.
Si può anche inserire un Google Breakpad lì, in modo che ogni volta che si preme un puntatore NULL si invia un report con lo stack completo in quel punto.

Nei casi in cui un puntatore NULL è possibile (e talvolta previsto ...), quindi suppongo che il controllo NULL sia migliore. Ma direi che a questo punto il tuo codice è sbagliato in qualche modo, se deve adattarsi con i puntatori NULL che vengono passati in giro.

+0

puoi spiegare molto su ** Google Breakpad ** con un piccolo campione? –

+0

Non hai http://code.google.com/p/google-breakpad/wiki/LinuxStarterGuide? – Gui13