Les variables de la stack sont-elles alignées par le CCG? __Atsortingbute __ ((aligné (x)))?

J’ai le code suivant:

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

Et j’ai la sortie suivante:

 0x7fffbfcd2da0 0x7fffbfcd2da4 0x7fffbfcd2da8 0x7fffbfcd2dac 

Pourquoi l’adresse d’ a[0] n’est pas un multiple de 0x1000 ?

Qu’est-ce que __atsortingbute__((aligned(x))) exactement? J’ai mal compris cette explication?

J’utilise gcc 4.1.2.

Je crois que le problème est que votre tableau est sur la stack. Étant donné que le pointeur de la stack peut être quelque chose au démarrage de la fonction, il est impossible d’aligner le tableau sans en allouer beaucoup plus que nécessaire et en l’ajustant. Si vous déplacez le tableau hors de la fonction dans une variable globale, cela devrait fonctionner. L’autre chose que vous pouvez faire est de le garder comme variable locale (ce qui est une très bonne chose), mais le rendre static . Cela l’empêchera d’être stocké sur la stack. Attention, ces deux méthodes ne sont pas sûres pour les threads ou la récursivité, car il n’y aura qu’une seule copie du tableau.

Avec ce code:

 #include  float a[4] __atsortingbute__((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]); } 

J’ai compris:

 0x804c000 0x804c004 0x804c008 0x804c00c 

ce qui est attendu Avec votre code original, j’obtiens simplement des valeurs aléatoires comme vous l’avez fait.

Il y avait un bogue dans gcc qui entraînait un alignement des atsortingbuts pour ne pas fonctionner avec les variables de la stack. Il semble être corrigé avec le patch lié ci-dessous. Le lien ci-dessous contient également un peu de discussion sur le problème.

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

J’ai essayé votre code ci-dessus avec deux versions différentes de gcc: 4.1.2 à partir d’une boîte RedHat 5.7 et il a échoué de la même manière que votre problème (les tableaux locaux n’étaient en aucun cas alignés sur les limites de 0x1000 octets). J’ai ensuite essayé votre code avec gcc 4.4.6 sur RedHat 6.3, et cela fonctionnait parfaitement (les tableaux locaux étaient alignés). Les gens de Myth TV avaient un problème similaire (que le patch gcc au-dessus semblait corriger):

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

Quoi qu’il en soit, il semble que vous ayez trouvé un bogue dans gcc, qui semble avoir été corrigé dans les versions ultérieures.

Les GCC récents (testés avec 4.5.2-8ubuntu4) semblent fonctionner comme prévu avec le tableau aligné correctement.

 #include  int main(void) { float a[4] = { 1.0, 2.0, 3.0, 4.0 }; float b[4] __atsortingbute__((aligned(0x1000))) = { 1.0, 2.0, 3.0, 4.0 }; float c[4] __atsortingbute__((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]); } 

Je reçois:

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

L’alignement n’est pas efficace pour tous les types. Vous devriez envisager d’utiliser une structure pour voir les atsortingbuts en action:

 #include  struct my_float { float number; } __atsortingbute__((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]); } 

Et puis, vous allez lire:

 0x603000 0x604000 0x605000 0x606000 

C’est ce que vous attendiez.

Edit: Poussé par @yzap et suivant le commentaire de @Caleb Case, le problème initial est uniquement dû à la version de GCC. J’ai vérifié sur GCC 3.4.6 vs GCC 4.4.1 avec le code source du demandeur:

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

Il est maintenant évident que les anciennes versions de GCC (quelque part avant 4.4.1) montrent des pathologies d’alignement.

Note 1: Mon code proposé ne répond pas à la question que j’ai comprise comme “alignant chaque champ du tableau”.

Note 2: Le fait de comstackr un fichier [] non statique dans main () et de le comstackr avec GCC 3.4.6 rompt la directive d’alignement du tableau de struct tout en conservant la distance 0x1000 entre les structs … toujours mauvaise! (voir la réponse de @zifre pour des solutions de contournement)