¿Las variables de la stack están alineadas por GCC __attribute __ ((aligned (x)))?

tengo el siguiente código:

#include  int main(void) { float a[4] __attribute__((aligned(0x1000))) = {1.0, 2.0, 3.0, 4.0}; printf("%p %p %p %p\n", &a[0], &a[1], &a[2], &a[3]); } 

Y tengo el siguiente resultado:

 0x7fffbfcd2da0 0x7fffbfcd2da4 0x7fffbfcd2da8 0x7fffbfcd2dac 

¿Por qué la dirección de a[0] no es un múltiplo de 0x1000 ?

¿Qué exactamente __attribute__((aligned(x))) hace? ¿Entendí mal esta explicación?

Estoy usando gcc 4.1.2.

Creo que el problema es que tu matriz está en la stack. Debido a que el puntero de stack puede ser cualquier cosa cuando se inicia la función, no hay forma de alinear la matriz sin asignar mucho más de lo que necesita y ajustarlo. Si mueve la matriz de la función a una variable global, debería funcionar. La otra cosa que podrías hacer es mantenerlo como una variable local (que es algo muy bueno), pero hacerlo static . Esto evitará que se almacene en la stack. Tenga en cuenta que estas dos formas no son seguras para subprocesos ni seguridad de recursión, ya que solo habrá una copia de la matriz.

Con este código:

 #include  float a[4] __attribute__((aligned(0x1000))) = {1.0, 2.0, 3.0, 4.0}; int main(void) { printf("%p %p %p %p\n", &a[0], &a[1], &a[2], &a[3]); } 

Entiendo esto:

 0x804c000 0x804c004 0x804c008 0x804c00c 

que es lo que se espera Con su código original, obtengo valores aleatorios como los que hizo.

Hubo un error en gcc que causaba que los atributos alineados no funcionaran con las variables de la stack. Parece que se corrigió con el parche vinculado a continuación. El siguiente enlace también contiene bastante debate sobre el problema.

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=16660

He intentado con tu código anterior con dos versiones diferentes de gcc: 4.1.2 de un cuadro RedHat 5.7, y falló de manera similar a tu problema (las matrices locales no estaban alineadas de ninguna manera con los límites de 0x1000 bytes). Luego probé tu código con gcc 4.4.6 en RedHat 6.3, y funcionó sin problemas (las matrices locales estaban alineadas). La gente de Myth TV tenía un problema similar (que el parche gcc anterior parecía arreglar):

http://code.mythtv.org/trac/ticket/6535

De todos modos, parece que encontraste un error en gcc, que parece corregido en versiones posteriores.

Los GCC recientes (probados con 4.5.2-8ubuntu4) parecen funcionar como se esperaba con la matriz alineada correctamente.

 #include  int main(void) { float a[4] = { 1.0, 2.0, 3.0, 4.0 }; float b[4] __attribute__((aligned(0x1000))) = { 1.0, 2.0, 3.0, 4.0 }; float c[4] __attribute__((aligned(0x10000))) = { 1.0, 2.0, 3.0, 4.0 }; printf("%p %p %p %p\n", &a[0], &a[1], &a[2], &a[3]); printf("%p %p %p %p\n", &b[0], &b[1], &b[2], &b[3]); printf("%p %p %p %p\n", &c[0], &c[1], &c[2], &c[3]); } 

Yo obtengo:

 0x7ffffffefff0 0x7ffffffefff4 0x7ffffffefff8 0x7ffffffefffc 0x7ffffffef000 0x7ffffffef004 0x7ffffffef008 0x7ffffffef00c 0x7ffffffe0000 0x7ffffffe0004 0x7ffffffe0008 0x7ffffffe000c 

La alineación no es efectiva para todos los tipos. Debería considerar usar una estructura para ver los atributos en acción:

 #include  struct my_float { float number; } __attribute__((aligned(0x1000))); struct my_float a[4] = { {1.0}, {2.0}, {3.0}, {4.0} }; int main(void) { printf("%p %p %p %p\n", &a[0], &a[1], &a[2], &a[3]); } 

Y luego, leerás:

 0x603000 0x604000 0x605000 0x606000 

Que es lo que estabas esperando.

Editar: Empujado por @yzap y siguiendo el comentario de @Caleb Case, el problema inicial se debe solo a la versión de GCC. Revisé GCC 3.4.6 vs GCC 4.4.1 con el código fuente del solicitante:

 $ ./test_orig-3.4.6 0x7fffe217d200 0x7fffe217d204 0x7fffe217d208 0x7fffe217d20c $ ./test_orig-4.4.1 0x7fff81db9000 0x7fff81db9004 0x7fff81db9008 0x7fff81db900c 

Ahora es obvio que las versiones anteriores de GCC (en algún lugar antes de 4.4.1) muestran patologías de alineación.

Nota 1: Mi código propuesto no responde la pregunta que entendí como “alinear cada campo de la matriz”.

Nota 2: Traer no estático a [] dentro de main () y comstackr con GCC 3.4.6 rompe la directiva de alineación de la matriz de struct pero mantiene la distancia 0x1000 entre las estructuras … ¡sigue siendo malo! (vea la respuesta de @zifre para las soluciones)