¿Las variables de pila están alineadas por el atributo GCC ((aligned (x)))?
Tengo el siguiente código:
#include <stdio.h>
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 la siguiente salida:
0x7fffbfcd2da0 0x7fffbfcd2da4 0x7fffbfcd2da8 0x7fffbfcd2dac
¿por Qué la dirección de a[0]
no es un múltiplo de 0x1000
?
¿Qué hace exactamente __attribute__((aligned(x)))
? ¿Malinterpreté esta explicación?
Estoy usando gcc 4.1.2.
4 answers
Creo que el problema es que su matriz está en la pila. Debido a que el puntero de pila podría ser cualquier cosa cuando se inicia la función, no hay manera de alinear la matriz sin asignar mucho más de lo que necesita y ajustarlo. Si mueve la matriz fuera de la función y a una variable global, debería funcionar. La otra cosa que podrías hacer es mantenerla como una variable local (lo cual es algo muy bueno), pero que sea static
. Esto evitará que se almacene en la pila. Cuidado que ambos de estas formas no son seguras para subprocesos o recursivas, ya que solo habrá una copia de la matriz.
Con este código:
#include <stdio.h>
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 tu código original, solo obtengo valores aleatorios como lo hiciste tú.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-05-08 19:51:58
Hubo un error en gcc que causó que el atributo alineado no funcionara con variables de pila. Parece arreglarse con el parche vinculado a continuación. El siguiente enlace también contiene un poco de discusión para el problema también.
Http://gcc.gnu.org/bugzilla/show_bug.cgi?id=16660
He probado el código anterior con dos versiones diferentes de gcc: 4.1.2 de un RedHat 5.7 cuadro, y falló de manera similar a su problema (los arrays locales wre de ninguna manera alineado en 0x1000 byte boundaies). Luego probé su código con gcc 4.4.6 en RedHat 6.3, y funcionó sin problemas (los arrays locales estaban alineados). La gente de Myth TV tenía un problema similar (que el parche de gcc anterior parecía arreglar):
Http://code.mythtv.org/trac/ticket/6535
De todos modos, parece que ha encontrado un error en gcc, que parece ser corregido en versiones posteriores.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-10-15 22:17:45
Los GCC recientes (probados con 4.5.2-8ubuntu4) parecen funcionar como se esperaba con la matriz alineada correctamente.
#include <stdio.h>
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]);
}
Obtengo:
0x7ffffffefff0 0x7ffffffefff4 0x7ffffffefff8 0x7ffffffefffc
0x7ffffffef000 0x7ffffffef004 0x7ffffffef008 0x7ffffffef00c
0x7ffffffe0000 0x7ffffffe0004 0x7ffffffe0008 0x7ffffffe000c
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-05-04 02:36:16
La alineación no es efectiva para todos los tipos. Deberías considerar usar una estructura para ver los atributos en acción:
#include <stdio.h>
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 esperabas.
Editar: Empujado por @yzap y siguiendo el comentario del caso @Caleb, el problema inicial se debe a la versión de GCC solo. He comprobado en 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 más antiguas de GCC (en algún lugar antes de 4.4.1) muestra patologías de alineación.
Nota 1: Mi código propuesto no responde a la pregunta que entendí como "alinear cada campo del array".
Nota 2: Traer un [] no estático dentro de main() y compilar con GCC 3.4.6 rompe la directiva de alineación de la matriz de struct pero mantiene una distancia de 0x1000 entre estructuras... ¡sigue siendo malo ! (ver @zifre respuesta para soluciones alternativas)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-03-23 00:01:24