c - usar - usos de las tag questions
¿Cómo hacer que gcc advierta una estructura indefinida? (2)
Tengo una estructura definida en .h
struct buf_stats {
// ***
};
luego en el archivo .c
struct buf_stats *bs = malloc(sizeof(struct buf_states*)) ;
donde buf_states
es un error tipográfico.
pero gcc no me advierte, aunque utilicé -Wall
y este error / error me costó 3 horas para averiguarlo.
¿Cómo hacer que gcc advierta una estructura indefinida como esta?
En tu codigo
struct buf_stats *bs = malloc(sizeof(struct buf_states*)) ;
está mal por muchas razones, como
- Está utilizando un tipo indefinido (como mencionó)
- Está asignando menos memoria (asignando un puntero a tipo en lugar del tipo )
Pero su compilador no puede ayudar mucho en _this_case para este tipo particular de error, como
un puntero a ( cualquier ) tipo en una plataforma tiene un tamaño definido, por lo que la estructura (es decir, el tipo de la variable a la que apunta) no necesita estar completa ( definida ). Esta es la razón por la que podemos tener estructuras de auto-referencia, ¿verdad?
malloc()
no tiene idea sobre el tipo de variable de destino. Simplemente lee el argumento para el tamaño necesario, devuelve un puntero (que es de tipovoid *
) a la memoria asignada y, tras la asignación, se cambia al tipo de destino. No es posible calcular la falta de coincidencia en el tamaño (tipo) de destino con el tamaño de memoria asignado.
La forma más conveniente y sencilla de evitar este tipo de errores es no usar el tipo codificado directamente como el operando de sizeof
, sino usar la referencia de la variable.
Algo como
struct buf_stats *bs = malloc(sizeof *bs) ; // you can write that as (sizeof (*bs)) also
// sizeof *bs === sizeof (struct buf_stats)
que es equivalente a
struct buf_stats *bs = malloc(sizeof(struct buf_stats)) ;
pero es más robusto y menos propenso a errores.
Notas:
- No necesita el paréntesis si el operando no es un nombre de tipo .
- Esta declaración no necesita ninguna modificación al cambiar el tipo de variable objetivo
bs
.
Usted no puede El uso de una expresión como struct foo *
(un puntero a algún tipo de estructura) declara que la estructura es un tipo incompleto . No se conoce un tamaño, pero no es necesario para el tamaño del puntero .
Dicho esto, el código parece incorrecto, ya que necesita el tamaño de la estructura ( no el tamaño del puntero), así que con el siguiente código:
struct buf_stats *bs = malloc(sizeof(struct buf_states));
obtendrías un error
Hay una mejor manera de escribir dicho código:
struct buf_stats *bs = malloc(sizeof *bs);
La expresión *bs
tiene el tipo correcto para sizeof
, incluso cuando más tarde cambia el tipo.