Pergunta

Eu tenho o seguinte 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]);
}

E eu tenho o seguinte resultado:

0x7fffbfcd2da0 0x7fffbfcd2da4 0x7fffbfcd2da8 0x7fffbfcd2dac

Por que o endereço do a[0] não é um múltiplo de 0x1000?

O que exatamente __attribute__((aligned(x))) faz? Eu mal entendido este explicação?

Eu estou usando gcc 4.1.2.

Foi útil?

Solução

Eu acredito que o problema é que sua matriz está na pilha. Porque o ponteiro da pilha poderia ser qualquer coisa quando a função começa, não há nenhuma maneira de alinhar a matriz sem alocar muito mais do que você precisa e ajustá-lo. Se você mover a matriz fora da função e em uma variável global, ele deve funcionar. A outra coisa que você poderia fazer é mantê-lo como uma variável local (que é uma coisa muito boa), mas torná-lo static. Isso vai impedir que ele seja armazenado na pilha. Tenha em atenção que ambas as formas não são thread-safe ou recursão-seguro, uma vez que haverá apenas uma cópia da matriz.

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]);
}

fico com esta:

0x804c000 0x804c004 0x804c008 0x804c00c

que é o que se espera. Com o seu código original, eu só obter valores aleatórios como você fez.

Outras dicas

Houve um erro no gcc que causou atributo alinhadas para não trabalhar com variáveis ??de pilha. Parece ser fixo com o remendo ligada abaixo. O link abaixo contém também um pouco de discussão para o problema também.

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

Eu tentei o código acima, com duas versões diferentes do gcc: 4.1.2 a partir de uma RedHat 5.7 caixa, e não deu igualmente o seu problema (as matrizes locais wre em nada alinhado 0x1000 boundaies bytes). Então eu tentei o seu código com gcc 4.4.6 no RedHat 6.3, e funcionou sem falhas (as matrizes locais foram alinhadas). O pessoal Myth TV teve um problema semelhante (que o patch gcc acima parecia correção):

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

De qualquer forma, parece que você encontrou um bug no gcc, que parece ser corrigido em versões posteriores.

GCC recentes (testado com 4.5.2-8ubuntu4) parecem funcionar como esperado com a matriz alinhada 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

Alignement 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, em seguida, você vai ler:

0x603000 0x604000 0x605000 0x606000

O que é que você estava esperando.

Editar: Empurrado por @yzap e seguinte comentário @Caleb caso, o problema inicial é devido a versão do GCC única . Eu verifiquei no 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 patologias versões mais antigas do GCC (em algum lugar antes 4.4.1) mostra alinhamento.

Nota 1: Meu código proposto não responder à pergunta que eu entendi como "alinhando cada campo da matriz"

.

Nota 2: Trazendo um não-estático [] dentro de main () e compilar com GCC 3.4.6 breaks da directiva alinhamento da matriz de struct, mas mantém 0x1000 distância entre estruturas ... ainda ruim! (Veja @zifre resposta para soluções alternativas)

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top