2009-12-21 9 views
78

Teoricamente posso dire cheDoes free (ptr) dove ptr è NULL memoria corrotta?

free(ptr); 
free(ptr); 

è una corruzione della memoria dato che stiamo liberare la memoria che è già stato liberato.

Ma cosa succede se

free(ptr); 
ptr=NULL; 
free(ptr); 

come sistema operativo si comporterà in maniera indefinita non riesco a ottenere un'analisi teorica effettivo per questo su quello che succede. Qualunque cosa stia facendo, è questa corruzione della memoria o no?

È possibile liberare un puntatore NULL valido?

+1

sicuro di C standard gratuita, ma in C++ delete (NULL) è perfettamente valido, quindi credo che libera (NULL) dovrebbe anche essere. –

+11

@Pryank: 'delete NULL' non è valido in C++. delete può essere applicato ai valori null-pointer del tipo concreto, ma non a 'NULL'. 'delete (int *) NULL' è legale, ma non' delete NULL'. – AnT

+0

quindi vuol dire che se un puntatore punta a NULL libero non esegue nulla. Ciò significa che !!!!!! ogni volta nella nostra codifica se vuoi liberare una memoria puoi semplicemente sostituire un libero (ptr) con ptr = NULL? – Vijay

risposta

179

7.20.3.2 La free funzione

Trama

#include <stdlib.h> 
void free(void *ptr); 

Descrizione

La funzione free provoca lo spazio puntato da ptr essere deallocato, cioè, reso disponibile per ulteriore assegnazione. Se ptr è un puntatore nullo, non si verifica alcuna azione.

Vedere ISO-IEC 9899.

Detto questo, se si considerano diverse basi di codice in natura, si noterà la gente a volte lo fanno:

if (ptr) 
    free(ptr); 

Questo perché alcuni runtime C (i di sicuro ricordo che era il caso su PalmOS) si arresterebbe in modo anomalo quando si libera un puntatore NULL.

Ma al giorno d'oggi, credo che sia sicuro assumere free(NULL) è un nop come da istruzioni dello standard.

+3

+1 per sinossi. –

+0

quindi vuol dire che se un puntatore punta a NULL libero non esegue nulla. Ciò significa che !!!!!! ogni volta nella nostra codifica se vuoi liberare una memoria puoi semplicemente sostituire un libero (ptr) con ptr = NULL? – Vijay

+21

No, ptr = NULL non è un sostituto di free (ptr), entrambi sono completamente diversi –

0

non corruzione della memoria, ma il comportamento dipende dall'implementazione. Secondo lo standard, dovrebbe essere un codice legale.

10

Se ptr è NULL, non viene eseguita alcuna operazione.

dice la documentazione.

+0

vuoi dire che free non eseguirà nulla? – Vijay

+2

benjamin, questo è esattamente ciò che significa. Cosa ti aspetteresti che eseguisse se fosse a conoscenza della nullità dell'argomento? –

6

free(NULL) è perfettamente legale in C e delete (void *)0 e delete[] (void *)0 sono legali in C++.

BTW, liberare la memoria due volte di solito causa qualche tipo di errore di runtime, quindi non corrompe nulla.

+1

'delete 0' non è legale in C++. 'delete' richiede esplicitamente un'espressione di tipo puntatore. È legale applicare 'delete' a un valore di puntatore nullo tipizzato, ma non a' 0' (e non a 'NULL'). – AnT

+0

Yup, snippet fissi. – n0rd

+1

Non è possibile eliminare 'void *' neanche: P Quali distruttori devono essere eseguiti? – GManNickG

8
free(ptr); 
ptr=NULL; 
free(ptr);/*This is perfectly safe */ 

È possibile eliminare in modo sicuro un puntatore NULL. In questo caso nessuna operazione verrà eseguita. In altre parole free() non fa nulla su un puntatore NULL.

19

Tutte le versioni conformi agli standard della libreria C sono gratuite (NULL) come non operanti.

Detto questo, un tempo c'erano alcune versioni di libero che potrebbe andare in crash sulla libera (NULL), che è il motivo per cui è possibile vedere alcune tecniche di programmazione difensive raccomandano:

if (ptr != NULL) 
    free(ptr); 
+7

-1 [citazione necessaria]. Cambiare lo stile del codice a causa di alcune teorie di un'arcaica spiegazione per sentito dire è una cattiva idea. – Tomas

+25

@Tomas - Non ho mai raccomandato di cambiare stile, ho semplicemente spiegato perché potresti ancora vedere questa raccomandazione in alcuni stili. –

+3

@Tomas 3BSD (http://www.winehq.org/pipermail/wine-patches/2006-October/031544.html) e PalmOS per due (seconda mano per entrambi). –

7

utilizzo Recomended:

free(ptr); 
ptr = NULL; 

See:

man free 

    The free() function deallocates the memory allocation pointed to by ptr. 
    If ptr is a NULL pointer, no operation is performed. 

Quando si imposta il puntatore NULL dopo free() è possibile chiamare nuovamente free() e non verrà eseguita alcuna operazione.

+2

Ciò aiuta anche a individuare segfaults con un debugger. È evidente che segfault a p-> do() con p = 0 è qualcuno che usa un puntatore libero. Meno evidente quando vedi p = 0xbfade12 nel debugger :) – neuro

10

Ricordo di aver lavorato su PalmOS dove è stato arrestato free(NULL).

+3

Interessante - che rende una seconda piattaforma (dopo 3BSD) che si blocca. –

+1

Se ricordo male, su Palm la libreria C standard non esisteva. Invece, c'era un file di intestazione per lo più non supportato che associava le chiamate della libreria standard all'SDK di Palm OS. Molte cose hanno agito in modo imprevisto. L'arresto di 'NULL' era una delle maggiori differenze di esecuzione della casella degli strumenti Palm rispetto alla libreria standard. –

-1

ptr indica una posizione di memoria, diciamo 0x100.

Quando si è liberi (ptr), in pratica si sta consentendo 0x100 di essere utilizzato dal gestore della memoria per essere utilizzato per altre attività o processi e in parole semplici si tratta di deallocazione di risorse.

Quando si esegue ptr = NULL, si sta facendo punto ptr in una nuova posizione (non ci si deve preoccupare di cosa sia NULL). In questo modo hai perso la traccia dei dati di memoria 0x100. Si tratta di una perdita di memoria.

Quindi non è consigliabile utilizzare ptr = NULL su un ptr valido.

Invece si potrebbe fare un po 'di controllo di sicurezza utilizzando:

se {gratuito (PTR);}

Quando si liberi (PTR), dove PTR è già rivolto a NULL (PTR = NULL!) , non esegue alcuna operazione. Quindi, è sicuro di farlo.

0

libero (ptr) è salvato in C se ptr è NULL, tuttavia, ciò che la maggior parte delle persone non sa è che NULL non deve essere uguale a 0. Ho un bel esempio di vecchia scuola: Sul C64, su indirizzo 0, c'è una porta IO. Se hai scritto un programma in C che accede a questa porta, avresti bisogno di un puntatore il cui valore è 0. La libreria c corrispondente dovrebbe quindi distinguere tra 0 e NULL.

Cordiali saluti

non