Problemas de empaquetado del compilador de C
Los niveles de empaquetado afectan al diseño de memoria de los tipos para MIDL y el compilador de Microsoft C/C++ de la misma manera. En entornos de compilación de Microsoft, como el entorno de compilación definido por VC++ o el Kit de desarrollo de software de plataforma (SDK), el nivel de empaquetado predeterminado para los compiladores MIDL y C/C++ es el mismo; El nivel de empaquetado predeterminado para los entornos de compilación de Windows de 32 y 64 bits es de 8.
Alineación natural
En el caso de los tipos en memoria, la alineación predeterminada es la misma que su alineación natural.
- Un tipo base, como short, float y __int64, y un puntero se alinea naturalmente si su representación comienza en una dirección que es módulo de su tamaño. Todos los tipos base admitidos actualmente tienen tamaños de 1, 2, 4 o 8. Los punteros tienen un tamaño de 4 en entornos de 32 bits y 8 en entornos de 64 bits.
- Un tipo compuesto se alinea naturalmente si cada uno de sus componentes está alineado naturalmente con respecto al principio del tipo y si no hay espacios innecesarios (relleno) entre componentes. Los componentes compuestos, como campos o elementos, se repiten en componentes de tipo base o puntero.
Una regla sencilla para ayudar a recordar este comportamiento es que la alineación natural de un tipo es igual a las alineaciones más grandes de sus componentes.
Hay una conexión entre la alineación y el tamaño de memoria de un tipo en lenguajes como C o C++ e IDL, tal como se expresa en el operador sizeof(). El tamaño es un múltiplo de la alineación (el mínimo que abarca el tipo). Esto se deriva de una representación de matriz en la memoria.
La alineación natural es importante porque el acceso a datos mal alineados puede provocar una excepción en algunos sistemas. Los datos se pueden marcar para una manipulación segura cuando están mal alineados, pero normalmente eso implica una penalización de velocidad que puede ser sustancial en algunas plataformas.
Nota
En memoria, se garantiza que los objetos de tipos con una alineación natural de n se alinean correctamente cuando se colocan en direcciones que son un múltiplo de n.
Empaquetado frente a alineación
Especificar un nivel de empaquetado mayor que la alineación natural de un tipo no cambia la alineación del tipo. Si se especifica un nivel de empaquetado menor que la alineación natural, se reduce la alineación del tipo al nivel de empaquetado. Como resultado, los tipos empaquetados se pueden colocar en memoria en direcciones que son un múltiplo del nivel de empaquetado (la alineación reducida) sin causar una alineación incorrecta. Esto afecta tanto a tipos simples como a tipos de componentes. En el caso de los tipos compuestos, el diseño interno del tipo puede verse afectado, ya que la alineación reducida de los componentes puede cambiar el tamaño de relleno necesario para la alineación adecuada de los componentes, lo que reduce el tamaño del tipo.
Una regla sencilla para ayudar a recordar este comportamiento es que la nueva alineación de un tipo empaquetado es la menor del nivel de empaquetado y su alineación natural. El tamaño del tipo es un múltiplo de la nueva alineación. El operador sizeof() devuelve el tamaño reducido para los tipos empaquetados.
Por ejemplo, con el nivel de empaquetado 2, un largo se alinea en 2 y, por lo tanto, puede colocarse en cualquier dirección uniforme, no solo en las direcciones que son un múltiplo de 4, como sería el caso de la alineación natural. Una estructura con un corto y un largo, empaquetado en 2, no necesita la brecha interna entre el corto y el siguiente largo que fue necesario para la alineación natural; por lo tanto, no solo es la estructura ahora alineada en 2, sino que también tiene su tamaño reducido de 8 a 6.
Por ejemplo, considere un tipo compuesto que consta de un carácter de 1 byte, un entero de 4 bytes de longitud y un carácter de 1 byte:
struct mystructtype
{
char c1; /* requires 1 byte */
/* 3 bytes of padding with natural alignment only */
long l2; /* requires 4 bytes */
char c3; /* requires 1 byte */
/* 3 bytes of padding with natural alignment only */
} mystruct;
Esta estructura se alinea naturalmente en 4 y tiene el tamaño natural de 12.
Para el nivel de empaquetado 4 o superior, la estructura mystruct se alinea en 4 y sizeof(struct mystructtype)
es igual a 12. La estructura se desalineará si se encuentra en la memoria en una dirección que no es un múltiplo de 4.
Para el nivel de empaquetado 2, la estructura se alinea en 2 y su tamaño es 8. La estructura empaquetada con el nivel 2 se desalineará si se encuentra en la memoria en una dirección que no es múltiplo de 2.
Para el nivel de empaquetado 1, la estructura se alinea en 1 y su tamaño es 6. La estructura empaquetada con el nivel 1 se puede colocar en cualquier lugar sin causar un error de alineación incorrecta.
Temas relacionados