2009-12-16 12 views
18

Muchos punteros de código C liberando llama:comprobación de NULL antes de llamar gratis

if (p) 
    free(p); 

Pero por qué? Pensé que C estándar dice que la función free no hace nada dado un puntero NULL. Entonces, ¿por qué otro control explícito?

+12

¿Porque la gente no conoce el estándar C? –

+0

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

+2

WaffleMatt: eso es sobre C++ (y no C++ tag :-() - my es C, por lo que es un poco diferente. C++ es más nuevo así que tal vez los "viejos hábitos" tienen menos tracción allí – zaharpopov

Respuesta

16

El constructo:

free(NULL); 

siempre ha estado bien en C, de vuelta al compilador UNIX original escrita por Dennis Ritchie. Pre-estandarización, algunos compiladores pobres podrían no haberlo distribuido correctamente, pero en la actualidad cualquier compilador que no lo haga no puede legítimamente llamarse compilador del lenguaje C. Usarlo normalmente conduce a un código más claro y más fácil de mantener.

13

Según tengo entendido, la ausencia de NULL no siempre estaba allí.

En los malos tiempos de C (vuelta 1986, en un pre-estándar ANSI cc compilador) libre (NULL) sería un volcado de memoria. Así que la mayoría de los desarrolladores probaron NULL/0 antes de llamando gratis.

El mundo ha recorrido un largo camino, y parece que ya no necesitamos hacer la prueba . Pero los viejos hábitos son difíciles ;)

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

+0

+1 Esto es lo que recuerdo pero no pude encuentra la referencia. –

+0

Según tengo entendido, esta falla existía en algunos compiladores incluso después de la estandarización. –

+0

Siempre estuvo ahí, incluso en la implementación original de UNIX. Esto se menciona en el artículo de PJ Plauger sobre la estandarización. en proceso - no puede encontrar una referencia exacta en este momento. –

4

tiendo a escribir "if (p) free(p)" mucho, aunque sé que no es necesario.

Me culpo parcialmente porque aprendí C los viejos tiempos cuando free(NULL) segfault y todavía me siento incómodo al no hacerlo.

Pero también culpo al estándar C por no ser consistente. Gustaría, por ejemplo, fclose (NULL) estar bien definido, yo no tengo problemas por escrito:

free(p); 
fclose(f); 

que es algo que sucede muy a menudo cuando la limpieza de las cosas. Desafortunadamente, parece extraño para mí escribir

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

y termino con

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

que sé, no es una razón racional, sino que es mi caso :)

0

Si depende en ese libre (0) está BIEN, y es normal que su puntero sea nulo en este momento, por favor dígalo en el comentario // may be NULL

Esto puede ser meramente explicativo código natory, diciendo sí lo sé, también uso p como una bandera.

0

puede haber una implementación personalizada de free() en el entorno móvil. En ese caso, libre (0) puede causar un problema. (sí, mala implementación)

+3

Una nueva implementación de C, cuando se inicia hoy, no tiene excusa para producir dicho error. Los estándares C son claros en ese punto. – vog

2

Los compiladores, incluso cuando están en línea no son lo suficientemente inteligentes como para saber que la función volverá inmediatamente. Empujar los parámetros, etc. en la pila y configurar la llamada es obviamente más costoso que probar un puntero. Creo que siempre es una buena práctica evitar la ejecución de cualquier cosa, incluso cuando ese algo no sea operativo. La prueba de nulo es una buena práctica. Una práctica aún mejor es asegurarse de que su código no llegue a este estado y, por lo tanto, elimine por completo la necesidad de la prueba.

0

Hay dos razones distintas por las que una variable de puntero podría ser NULL:

  1. porque la variable se utiliza para lo que, en teoría, el tipo se llama un tipo opción, y tiene ya sea un puntero a un objeto , o NULL para representar nada,

  2. porque apunta a una matriz, y por lo tanto puede ser NULL si la matriz tiene longitud cero (como malloc(0) se deja volver NULL, definido por la implementación).

Aunque esto es sólo una distinción lógica (en C no hay ni tipos de opción ni especiales punteros a las matrices de y que sólo tiene que utilizar punteros para todo), siempre debe quedar claro cómo una variable es usado.

Que el estándar C requiere free(NULL) para no hacer nada es la contrapartida necesaria para el hecho de que una llamada exitosa a malloc(0) puede devolver NULL. No es una conveniencia general, por lo que, por ejemplo, fclose()requiere un argumento que NO sea NULL. Abusar del permiso para llamar al free(NULL) al pasar un NULL que no represente una matriz de longitud cero es una sensación de hackeo e incorrecto.

0
if (p) 
    free(p); 

qué otra comprobación explícita?

Si que escribo algo por el estilo, es transmitir el conocimiento específico que el puntero puede ser NULL ... para ayudar en la lectura y comprensión del código. Porque se ve un poco raro para hacer que una aserción:

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

(Más allá de aspecto extraño, se sabe que los compiladores a quejarse de "condición siempre es cierto" si a su vez sus advertencias en muchos de estos casos.)

Así que lo veo como una buena práctica, si no está claro desde el contexto.

el caso contrario, de ser espera un puntero a ser no nula, suele ser evidente a partir de las anteriores líneas de código:

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

Pero si es no evidente, teniendo la aserción puede valer la pena los caracteres escritos

Cuestiones relacionadas