Acredito que o problema é que seu array está na pilha e que seu compilador é muito antigo para suportar variáveis de pilha superalinhadas. O GCC 4.6 e posterior corrigiu esse bug .
C11 / C ++ 11 alignas(64) float a[4];
simplesmente funciona para qualquer alinhamento de potência de 2.
O GNU C também__attribute__((aligned(x)))
conforme você o estava usando.
(Em C11, #include <stdalign.h>
para #define alignas _Alignas
: cppref ).
Mas no seu caso de um alinhamento muito grande, para um limite de página de 4k, você pode não querer isso na pilha.
Como o ponteiro da pilha pode ser qualquer coisa quando a função é iniciada, não há como alinhar a matriz sem alocar muito mais do que você precisa e ajustá-lo. (Compiladores irãoand rsp, -4096
ou equivalente e não usarão nenhum dos 0 a 4088 bytes alocados; ramificar se esse espaço é grande o suficiente ou não seria possível, mas não é feito porque grandes alinhamentos muito maiores que o tamanho da matriz ou outros locais não são o caso normal.)
Se você mover o array da função para uma variável global, ele deve funcionar. A outra coisa que você pode fazer é mantê-la como uma variável local (o que é uma coisa muito boa), mas faça-a static
. Isso evitará que ele seja armazenado na pilha. Esteja ciente de que ambas as formas não são seguras para threads ou recursivas, pois haverá apenas uma cópia do array.
Com 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]);
}
Eu entendi isso:
0x804c000 0x804c004 0x804c008 0x804c00c
que é o que se espera. Com seu código original, recebo apenas valores aleatórios como você fez.
alignas(64)
ou qualquer outra coisa em objetos com armazenamento automático. E, é claro, GNU C__attribute((aligned((64)))
Havia um bug no gcc que fazia com que o atributo alinhado não funcionasse com as variáveis da pilha. Parece estar corrigido com o patch vinculado abaixo. O link a seguir também contém uma boa discussão sobre o problema.
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=16660
Eu tentei seu código acima com duas versões diferentes do gcc: 4.1.2 de uma caixa RedHat 5.7, e ele falhou de forma semelhante ao seu problema (os arrays locais não estavam alinhados em limites de 0x1000 bytes). Então tentei seu código com gcc 4.4.6 no RedHat 6.3, e funcionou perfeitamente (os arrays locais estavam alinhados). O pessoal da Myth TV teve um problema semelhante (que o patch gcc acima parecia corrigir):
http://code.mythtv.org/trac/ticket/6535
De qualquer forma, parece que você encontrou um bug no gcc, que parece ter sido corrigido nas versões posteriores.
fonte
memalign()
?GCC recente (testado com 4.5.2-8ubuntu4) parece funcionar como esperado com o array alinhado corretamente.
#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]); }
Eu recebo:
0x7ffffffefff0 0x7ffffffefff4 0x7ffffffefff8 0x7ffffffefffc 0x7ffffffef000 0x7ffffffef004 0x7ffffffef008 0x7ffffffef00c 0x7ffffffe0000 0x7ffffffe0004 0x7ffffffe0008 0x7ffffffe000c
fonte
O alinhamento não é eficaz para todos os tipos. Você deve considerar o uso de uma estrutura para ver os atributos em ação:
#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]); }
E então, você lerá:
0x603000 0x604000 0x605000 0x606000
Que é o que você esperava.
Edit: Empurrado por @yzap e seguindo @Caleb Caso comentário, o problema inicial é devido a versão do GCC única . Eu verifiquei GCC 3.4.6 vs GCC 4.4.1 com o código-fonte do solicitante:
$ ./test_orig-3.4.6 0x7fffe217d200 0x7fffe217d204 0x7fffe217d208 0x7fffe217d20c $ ./test_orig-4.4.1 0x7fff81db9000 0x7fff81db9004 0x7fff81db9008 0x7fff81db900c
Agora é óbvio que as versões mais antigas do GCC (em algum lugar antes de 4.4.1) mostram patologias de alinhamento.
Nota 1: Meu código proposto não responde à pergunta que entendi como "alinhar cada campo da matriz".
Nota 2: Trazer um não estático [] dentro de main () e compilar com GCC 3.4.6 quebra a diretiva de alinhamento do array de struct, mas mantém a distância de 0x1000 entre structs ... ainda ruim! (veja a resposta @zifre para soluções alternativas)
fonte