2009-12-16 11 views
18

Molti puntatori codice C liberando chiama:controllo per NULL prima di chiamare liberi

if (p) 
    free(p); 

Ma perché? Ho pensato che lo standard C dicesse che la funzione free non esegue nulla dato un puntatore NULL. Quindi, perché un altro controllo esplicito?

+12

Perché le persone non conoscono lo standard C? –

+0

Duplicato, ish of http://stackoverflow.com/questions/615355/is-there-any-reason-to-check-for-a-null-pointer-before-deleting – McPherrinM

+2

WaffleMatt: si tratta di C++ (e non Tag C++ :-() - my is C, quindi è un po 'diverso. C++ è più recente quindi forse' vecchie abitudini 'hanno meno trazione lì – zaharpopov

risposta

16

Il costrutto:

free(NULL); 

è sempre stato OK in C, di nuovo al compilatore UNIX originale scritto da Dennis Ritchie. Pre-standardizzazione, alcuni poveri compilatori potrebbero non averlo messo in campo correttamente, ma in questi giorni qualsiasi compilatore che non può legittimamente chiamarsi un compilatore per il linguaggio C. Usarlo normalmente porta a un codice più chiaro e più gestibile.

13

Come ho capito, il no-op su NULL non era sempre lì.

Nei vecchi giorni di C (indietro intorno 1986, su una pre-ANSI cc compilatore) libero (NULL) sarebbe core dump. Quindi la maggior parte degli sviluppatori è stata testata per NULL/0 prima della chiamata libera.

Il mondo ha fatto molta strada, e sembra che non abbiamo più bisogno di fare il test . Ma le vecchie abitudini non muoiono difficile;)

http://discuss.joelonsoftware.com/default.asp?design.4.194233.15

+0

+1 Questo è quello che ricordo ma non potevo trova il riferimento ad esso –

+0

A quanto ho capito, questo difetto esisteva in alcuni compilatori anche dopo la standardizzazione –

+0

Era sempre lì, anche nell'implementazione originale di UNIX, come accennato nell'articolo di PJ Plauger sullo standardisati in corso - non riesco a trovare il riferimento esatto in questo momento però. –

4

io tendo a scrivere "if (p) free(p)" molto, anche se so che non è necessario.

In parte mi sono incolpato perché ho imparato C ai vecchi tempi quando free(NULL) sarebbe segfault e mi sento ancora a disagio nel non farlo.

Ma anche la colpa dello standard C per non essere coerente. Sarebbe, per esempio, fclose (NULL) essere ben definito, non avrei problemi nella scrittura:

free(p); 
fclose(f); 

che è qualcosa che accade molto spesso quando ripulire le cose. Purtroppo, sembra strano per me di scrivere

free(p); 
if (f) fclose(f); 

e io alla fine con

if (p) free(p); 
if (f) fclose(f); 

Lo so, non è un motivo razionale, ma questo è il mio caso :)

0

Se ci si basa su questo gratuito (0) è OK, ed è normale che il puntatore sia nullo a questo punto, per favore dillo nel commento // may be NULL

Questo può essere semplicemente auto-spiegarsi codice natory, che dice sì, lo so, uso anche p come bandiera.

0

può esserci un'implementazione personalizzata di free() in ambiente mobile. In tal caso, l'assenza (0) può causare un problema. (sì, cattiva implementazione)

+3

Una nuova implementazione C, quando è stata avviata oggi, non ha scuse per produrre un bug di questo tipo. Gli standard C sono chiari in quel punto. – vog

2

I compilatori, anche quando sono in linea non sono abbastanza intelligenti da sapere che la funzione tornerà immediatamente. Spingere i parametri ecc sullo stack e impostare la chiamata su è ovviamente più costoso che testare un puntatore. Penso che sia sempre una buona pratica evitare l'esecuzione di qualsiasi cosa, anche quando questo è un no-op. Il test per null è una buona pratica. Una pratica ancora migliore è assicurarsi che il codice non raggiunga questo stato e quindi eliminare del tutto la necessità del test.

0

Ci sono due distinti motivi per cui una variabile puntatore potrebbe essere NULL:

  1. perché la variabile è utilizzato per quello che in teoria tipo viene chiamato un tipo opzione, e tiene sia un puntatore a un oggetto , o NULL per rappresentare nulla,

  2. perché rimanda a un array, e può quindi essere NULL se l'array ha lunghezza zero (come malloc(0) è consentito di restituire NULL, implementazione definita).

Anche se questa è solo una distinzione logica (in C non ci sono né tipi di opzioni né speciali puntatori ad array e ci basta usare punti di riferimento per tutto), dovrebbe sempre essere reso chiaro come una variabile è Usato.

Che lo standard C richiede free(NULL) per fare nulla è la contropartita necessaria al fatto che una chiamata riuscita a malloc(0) può restituire NULL. Non è inteso come una comodità generale, ed è per questo che ad esempio fclose()fa richiede un argomento non NULL. Abusare del permesso di chiamare free(NULL) passando un NULL che non rappresenti una matrice di lunghezza zero si sente in errore e hackish.

0
if (p) 
    free(p); 

perché un altro controllo esplicito?

Se ho scrivo una cosa del genere, è di trasmettere la conoscenza specifica che il puntatore può essere NULL ... per aiutare nella leggibilità e il codice di comprensione. Perché sembra un po 'strano per fare che un'asserzione:

assert(p || !p); 
free(p); 

(Al di là in cerca di strano, i compilatori sono noti per lamentarsi "condizione sempre vera" se si attiva tuoi avvertimenti in molti di questi casi.)

Quindi la vedo come una buona pratica, se non è chiara dal contesto.

Il caso opposto, di un puntatore dovrebbe diventare non nullo, di solito è evidente dalle precedenti linee di codice:

... 
Unhinge_Widgets(p->widgets); 
free(p); // why `assert(p)`...you just dereferenced it! 
... 

Ma se è non ovvio, avente l'asserzione può valere i personaggi digitati.

Problemi correlati