buscando NULL antes de llamar gratis

Muchos punteros de liberación de código C llamadas:

if (p) free(p); 

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

El constructo:

 free(NULL); 

Siempre ha estado bien en C, volviendo al comstackdor original de UNIX escrito por Dennis Ritchie. Antes de la estandarización, algunos comstackdores deficientes podrían no haberlo colocado correctamente, pero en estos días cualquier comstackdor que no pueda llamarse legítimamente un comstackdor para el lenguaje C. Usarlo generalmente lleva a un código más claro y más fácil de mantener.

Según tengo entendido, el no-op en NULL no siempre estuvo ahí.

En los viejos tiempos de C (en 1986, en un comstackdor de cc estándar pre-ANSI) gratis (NULL) volcaría el núcleo. Así que la mayoría de los desarrolladores probaron NULL / 0 antes de llamar gratis.

El mundo ha recorrido un largo camino y parece que ya no necesitamos hacer la prueba. Pero los viejos hábitos mueren duro;)

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

Tiendo a escribir ” if (p) free(p) ” mucho, incluso si sé que no es necesario.

Me culpo parcialmente porque aprendí C los viejos tiempos en que la free(NULL) fallaría y todavía me siento incómodo por no hacerlo.

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

 free(p); fclose(f); 

Que es algo que pasa muy a menudo a la hora de limpiar cosas. Desafortunadamente, me parece extraño escribir

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

y termino con

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

Lo sé, no es una razón racional pero ese es mi caso 🙂

Los comstackdores, incluso cuando los inlining no son lo suficientemente inteligentes como para saber que la función volverá inmediatamente. Presionar parámetros, etc. en la stack 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 esa no es una operación. La prueba de nulo es una buena práctica. Una práctica aún mejor es asegurarse de que su código no scope este estado y, por lo tanto, elimine la necesidad de la prueba por completo.

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

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

  1. porque la variable se usa para lo que en teoría de tipos se llama un tipo de opción y mantiene un puntero a un objeto o NULL para no representar nada

  2. porque apunta a una matriz y, por lo tanto, puede ser NULL si la matriz tiene una longitud cero (ya que malloc(0) puede devolver NULL, definida por la implementación).

Aunque esta es solo una distinción lógica (en C no hay tipos de opciones ni punteros especiales a los arreglos y solo usamos punteros para todo), siempre se debe aclarar cómo se usa una variable.

El hecho de que el estándar C requiera de forma free(NULL) para no hacer nada es la contrapartida necesaria al hecho de que una llamada exitosa a malloc(0) puede devolver NULL . No pretende ser una conveniencia general, por lo que, por ejemplo, fclose() requiere un argumento que no sea NULL. Abusar del permiso para llamar free(NULL) al pasar un NULL que no representa una matriz de longitud cero se siente mal y está mal.

Si confía en que gratis (0) está bien, y es normal que su puntero esté nulo en este punto, dígalo en el comentario // may be NULL

Esto puede ser simplemente un código autoexplicativo, diciendo que sí, lo sé, también uso p como una bandera .

 if (p) free(p); 

¿Por qué otro cheque explícito?

Si escribo algo así, es para transmitir el conocimiento específico de que el puntero puede ser NULO … para ayudar en la legibilidad y la comprensión del código. Porque parece un poco extraño hacer eso una afirmación:

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

(Más allá de parecer extraño, se sabe que los comstackdores se quejan de la “condición siempre verdadera” si usted activa sus advertencias en muchos de estos casos).

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

El caso inverso, de un puntero que se espera que no sea ​​nulo, suele ser evidente a partir de las líneas de código anteriores:

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

Pero si no es obvio, tener la afirmación puede valer la pena de los caracteres escritos.