Je pense que le problème est que votre tableau est sur la pile, et que votre compilateur est trop vieux pour supporter les variables de pile sur-alignées. GCC 4.6 et suivants correction de ce bug .
C11/C++11 alignas(64) float a[4];
Cela fonctionne pour tout alignement de puissance 2.
Il en va de même pour le GNU C __attribute__((aligned(x)))
pendant que vous l'utilisiez.
(En C11, #include <stdalign.h>
pour le #define alignas _Alignas
: cppref ).
Mais dans votre cas d'un très grand alignement, sur une frontière de page de 4k, vous ne voulez peut-être pas le mettre sur la pile.
Comme le pointeur de la pile peut être n'importe où au démarrage de la fonction, il n'y a aucun moyen d'aligner le tableau sans allouer beaucoup plus que nécessaire et l'ajuster. (Les compilateurs and rsp, -4096
ou équivalent et n'utiliser aucun des 0 à 4088 octets qui ont été alloués ; bifurquer sur le fait de savoir si cet espace est assez grand ou non serait possible mais n'est pas fait car les alignements énormes beaucoup plus grands que la taille du tableau ou d'autres locaux ne sont pas le cas normal).
Si vous déplacez le tableau hors de la fonction et dans une variable globale, cela devrait fonctionner. L'autre possibilité est de le conserver comme variable locale (ce qui est une très bonne chose), mais de le rendre static
. Cela l'empêchera d'être stocké sur la pile. Attention, ces deux méthodes ne sont pas sûres pour les threads ou les récursions, puisqu'il n'y aura qu'une seule copie du tableau.
Avec ce code :
#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]);
}
Je comprends :
0x804c000 0x804c004 0x804c008 0x804c00c
ce qui est attendu. Avec votre code original, j'obtiens juste des valeurs aléatoires comme vous l'avez fait.