Sizeof madness
¡Pasen! ¡Pasen y vean! Se trata de un problema que es recursivo en mi vida, viene de vez en cuando para darme dolores de cabeza hasta que recuerdo que esto me pasó hace ya unos años, otra vez :P.
Para que no se me vuelva a olvidar:
#include<stdio.h> struct structMadness { int a; char b; }; int main() { struct structMadness sm; printf("sizeof(int)=%d\n", sizeof(int)); printf("sizeof(char)=%d\n", sizeof(char)); printf("sizeof(sm)=%d\n", sizeof(sm)); return 0; }
Un programa sencillo, ¿no? Tenemos una estructura con un entero y un caracter, y mostramos por pantalla el tamaño de un entero, un caracter y de la estructura.
$ gcc main.c -o main $ ./main sizeof(int)=4 sizeof(char)=1 sizeof(sm)=8
¡Ahí está! El tamaño de a (4 bytes) más el tamaño de b (1 byte), suma... ¡8 bytes!
Pruébenlo en casa, no muerde.
Resulta que el compilador, al reservar memoria para la estructura, está alineándola a 32 bits (en mi caso el int
son 32 bits, el char
son 8 bits, así que añade 24 bits más para ser múltiplo de 32). Esto podemos comprobarlo con un gcc -S main.c
para ver el código ensamblador que genera, donde se aprecia un align 4 (en mi caso, GCC 2.95.4).
Bueno, esto es así y hay que convivir con ello. Cualquier compilador nos permitirá compactar la estructura de forma que no haya alineamiento (bueno, sí lo hay... pero es al byte, lo cual no nos causará problemas).
Cambiamos la estructura por:
struct structMadness { int a; char b; } __attribute__ ((packed));
Ahora repetimos la ejecución:
$ ./main sizeof(int)=4 sizeof(char)=1 sizeof(sm)=5
Bien, esto ya es más razonable ;).
¿Dónde puede ser esto un problema? Cuando leemos una estructura de disco. Si se grabó compactada, hay que leerla compactada, sino el alineamiento nos hará leer de más (o de menos si leemos compactando una estructura que se grabó sin compactar :D).
Además podría darse un caso en el que el alineamiento no fuera siempre de 32 bits, con los que datos guardados/leídos con alineamientos diferentes llevarían a error al recuperar los datos guardados.
Espero que no se me vuelva a olvidar.
Hay 2 comentarios
Si tienes que grabar/leer una estructura compleja a/de disco, una struct es la forma natural de hacerlo, pero sin compactar (el término no se si será ese en castellano...), no funcionará siempre como se espera porque la disposición en memoria no corresponde con la distribución de los elementos y sus tamaños.
Grabar/leer 1 elemento (estructura) es más sencillo que hacerlo con cada uno de sus componentes, así que es bueno conocer estas particularidades...
Los comentarios están cerrados: los comentarios se cierran automáticamente una vez pasados 30 días. Si quieres comentar algo acerca de la anotación, puedes hacerlo por e-mail.
por ebarbeito, en 2005-02-08 17:05:32 ∞