Estoy leyendo un libro ( Programación con hilos POSIX de Butenhof, 1997) que usa C, y me encontré con la siguiente línea:
(void)free(data);
Aquí, data
es solo un puntero a una estructura asignada,
data = malloc(sizeof(my_struct_t));
¿Por qué es el resultado de free
ser lanzado a void
?
Desde mi entendimiento de C, esto no parece tener sentido por dos razones:
- La función libre ya regresa
void
- El código no usa el valor de retorno (ni siquiera se le asigna a una variable)
El libro fue escrito en 1997. ¿Es esto una especie de legado?
El autor menciona que los ejemplos se ejecutaron en Digital Unix 4.0d, pero todavía no puedo imaginar una razón para emitir el resultado de una función si no va a utilizar ese resultado.
free()
como una rareza en el libro que no necesita emular. Era semi-relevante hace mucho tiempo, pero ya no es relevante.Respuestas:
Si estamos hablando de la
free
función estándar , entonces su prototipo esPor lo tanto, el elenco es completamente inútil.
Ahora algo de especulación.
Es posible que el autor haya olvidado incluir el
stdlib.h
encabezado que declara este prototipo, por lo que el compilador asume el tipo de retorno comoint
. Ahora, durante el análisis estático de este código, el compilador advirtió sobre el valor de retorno no utilizado de lo que considera que novoid
funciona. Advertencias a tales suelen ser silenciados por la adición al elenco avoid
.fuente
free
que realmente tiene, con el resultado de que la llamada tiene un comportamiento indefinido (suponiendo que la semántica C90, donde llamar a una función no declarada no exhibe inherentemente UB en todos los casos). En la práctica, es plausible que eso resulte en un mal comportamiento de buena fe en algunos sistemas. La solución correcta es proporcionar una declaración correcta para la función.¡Sería un legado!
Antes de que hubiera un estándar C, la
free()
función habría sido (implícitamente) de tipoint
, porque todavía no había un tipo confiablevoid
para que regresara. No hubo valor devuelto.Cuando el código se modificó por primera vez para que funcione con compiladores C estándar, probablemente no lo incluyó
<stdlib.h>
(porque no existía antes del estándar). El código antiguo escribiríaextern char *malloc();
(tal vez sin elextern
) para las funciones de asignación (de manera similar paracalloc()
yrealloc()
), y no necesitaba declararfree()
. Y el código arrojaría el valor de retorno al tipo correcto, porque eso era necesario en al menos algunos sistemas (incluido el que aprendí en C).Algún tiempo después, el
(void)
elenco se agregó para decirle al compilador (o, más probablementelint
) que "el valor de retornofree()
se ignora deliberadamente" para evitar una queja. Pero hubiera sido mejor agregar<stdlib.h>
y dejar que su declaración leextern void free(void *vp);
dijeralint
al compilador que no había valor que ignorar.JFTR: A mediados de los '80, el ICL Perq estaba originalmente en una arquitectura orientada a palabras y la
char *
dirección para una ubicación de memoria era un número muy diferente del 'apuntador_superior' a la misma ubicación. Era crucial declarar dechar *malloc()
alguna manera; Era crucial transmitir el resultado a cualquier otro tipo de puntero. El elenco en realidad cambió el número utilizado por la CPU. (También hubo mucho regocijo cuando la memoria principal en nuestros sistemas se actualizó de 1 MiB a 2 MiB, ya que el núcleo usaba aproximadamente 3/4 MiB, significaba que los programas de usuario podían usar 1 1/4 MiB antes de la paginación, etc.)fuente
free()
p. 177 que regresa implícitamenteint
.void
se agregó a algunos sistemas (Unix System III, tal vez) antes del lanzamiento del estándar, pero eso no era parte de C cuando se escribió K&R 1st Edn (1978). Una función que no devolvió un valor se declaró sin un tipo de retorno (lo que significa que se devolvióint
), y siempre que no haya utilizado el valor que no se devolvió, no hubo ningún problema. El estándar C90 tuvo que tratar ese tipo de código como válido: habría fallado lamentablemente como un estándar si no lo hubiera hecho. Pero C99 eliminó lasint
reglas 'implícita ' y 'declaración de función implícita'. No todo el código del mundo se ha puesto al día.(void)
yeso paraprintf()
?Este yeso no es necesario. Probablemente no hubiera sido en ese momento, ya que C se había estandarizado en forma de C89.
Si lo hubiera sido, habría sido debido a una declaración implícita . Esto generalmente significaba que la persona que escribía el código se olvidó
#include <stdlib.h>
y que se estaba utilizando un analizador estático. Esta no es la mejor solución y una idea mucho mejor hubiera sido simplemente#include <stdlib.h>
hacerlo. Aquí hay algunas palabras de C89 sobre la declaración implícita:Pero eso es extraño porque no están emitiendo el resultado de
malloc
ninguno de los dos,malloc
yfree
están en el mismo archivo de encabezado.También es posible que esto sea solo un error o alguna forma de decirle al lector que
free
no devuelve ningún resultado.fuente
free
pero no paramalloc
.