Pergunta

Estou portando um aplicativo para uma plataforma de ARM em C, o aplicativo também é executado em um processador X86 e deve ser compatível com versões anteriores.

Agora estou tendo alguns problemas com o alinhamento variável. Eu li o manual do GCC para__attribute__((aligned(4),packed)) Eu interpreto o que está sendo dito, pois o início da estrutura está alinhado aos limites de 4 bytes e o interior permanece intocado por causa da declaração lotada.

Originalmente, eu tinha isso, mas ocasionalmente ele é colocado sem alinhado com o limite de 4 bytes.

typedef struct  
{  
 unsigned int code;  
 unsigned int length;  
 unsigned int seq;  
 unsigned int request;  
 unsigned char nonce[16];  
 unsigned short  crc;  
} __attribute__((packed)) CHALLENGE;

Então eu mudo para isso.

typedef struct  
{  
 unsigned int code;  
 unsigned int length;  
 unsigned int seq;  
 unsigned int request;  
 unsigned char nonce[16];  
 unsigned short  crc;  
} __attribute__((aligned(4),packed)) CHALLENGE;

O entendimento que afirmei anteriormente parece estar incorreto, pois a estrutura agora está alinhada a um limite de 4 bytes, e os dados internos agora estão alinhados a um limite de quatro bytes, mas por causa da endianesa, o tamanho da estrutura aumentou em Tamanho de 42 a 44 bytes. Esse tamanho é crítico, pois temos outras aplicações que dependem da estrutura de 42 bytes.

Alguns poderiam me descrever como executar a operação necessária. Qualquer ajuda é muito apreciada.

Foi útil?

Solução

Se você depende de sizeof(yourstruct) Sendo 42 bytes, você está prestes a ser mordido por um mundo de suposições não portáveis. Você não disse para o que é isso, mas parece provável que a endianidade do conteúdo da estrutura também seja importante, para que você também possa ter uma incompatibilidade com o X86 lá também.

Nesta situação, acho que a única maneira segura de lidar é usar unsigned char[42] nas partes onde isso importa. Comece escrevendo uma especificação precisa de exatamente quais campos estão onde neste bloco de 42 bytes e qual endian, use essa definição para escrever algum código para traduzir entre isso e uma estrutura com a qual você pode interagir. O código provavelmente será o código de serialização de tudo o que é o que é um bando de getters e setters.

Outras dicas

Essa é uma das razões pelas quais a leitura de estruturas inteiras, em vez de falha, e deve ser evitada.

Nesse caso, a embalagem mais alinhada em 4 significa que haverá dois bytes de preenchimento. Isso acontece porque o tamanho deve ser compatível para armazenar o tipo em uma matriz com todos os itens ainda alinhados em 4.

Eu imagino que você tem algo como:

read(fd, &obj, sizeof obj)

Como você não quer ler aqueles 2 bytes que pertencem a dados diferentes, você deve especificar o tamanho explicitamente:

read(fd, &obj, 42)

Que você pode manter manutenção:

typedef struct {
  //...
  enum { read_size = 42 };
} __attribute__((aligned(4),packed)) CHALLENGE;

// ...

read(fd, &obj, obj.read_size)

Ou, se você não pode usar alguns recursos de C ++ em seu C:

typedef struct {
  //...
} __attribute__((aligned(4),packed)) CHALLENGE;
enum { CHALLENGE_read_size = 42 };

// ...

read(fd, &obj, CHALLENGE_read_size)

Na próxima oportunidade de refatoração, sugiro fortemente que você comece a ler cada membro individualmente, o que pode ser facilmente encapsulado dentro de uma função.

Qual é o seu verdadeiro objetivo?

Se é para lidar com dados que estão em um arquivo ou no fio em um formato específico, o que você deve fazer é escrever algumas rotinas de marechaling/serialização que movem os dados entre a estrutura do compilador que representa como você deseja lidar com os dados dentro dos dados dentro dos programa e uma matriz de char que lida com a aparência dos dados no fio/arquivo.

Então tudo isso precisa ser tratado com cuidado e possivelmente com código específico da plataforma são as rotinas de marechaling. E você pode escrever alguns testes de unidade de bom-nativo para garantir que os dados organizados cheguem de e para a estrutura corretamente, independentemente da plataforma que você possa ter para portar hoje e no futuro.

Eu tenho movido estruturas para frente e para trás do Linux, Windows, Mac, C, Swift, Assembly, etc.

O problema não é que isso não pode ser feito, o problema é que você não pode ser preguiçoso e deve entender suas ferramentas.

Não vejo por que você não pode usar:

typedef struct  
{  
 unsigned int code;  
 unsigned int length;  
 unsigned int seq;  
 unsigned int request;  
 unsigned char nonce[16];  
 unsigned short  crc;  
} __attribute__((packed)) CHALLENGE;

Você posso Use -o e não requer nenhum código especial ou inteligente. Eu escrevo muito código que se comunica com o Arm. Estruturas são o que fazem as coisas funcionarem. __attribute__ ((packed)) é meu amigo.

As chances de estar em um "mundo da mágoa" são nulos se você entende o que está acontecendo com os dois.

Finalmente, não posso para a vida entender como você recebe 42 ou 44. Int é 4 nossos 8 bytes (dependendo do compilador). Isso coloca o número em 16+16+2 = 34 ou 32+16+2 = 50 - assumindo que seja realmente embalado.

Como eu disse, conhecer suas ferramentas faz parte do seu problema.

Eu acho que o problema é que 42 não é divisível por 4 e, portanto, eles ficam fora do alinhamento se você colocar várias dessas estruturas de volta (por exemplo, alocam memória para vários deles, determinando o tamanho com sizeof). Ter o tamanho como 44 força o alinhamento nesses casos, conforme solicitado. No entanto, se o deslocamento interno de cada membro da estrutura permanecer o mesmo, você poderá tratar a estrutura de 44 bytes como se fosse 42 bytes (desde que você tome cuidado para alinhar todos os dados seguintes no limite correto).

Um truque para tentar pode estar colocando Ambas Destas estruturas dentro de um único tipo de união e usa apenas uma versão de 42 bytes de cada união.

Enquanto estou usando o Linux, descobri isso por echo 3 > /proc/cpu/alignment Isso me emitirá com um aviso e corrigirá a questão do alinhamento. Esta é uma contorna, mas é muito útil para localizar onde as estruturas não estão desalinhadas.

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