Domanda

Io sono il porting di un'applicazione per una piattaforma ARM in C, l'applicazione viene eseguita anche su un processore x86, e deve essere compatibile.

Ora sto avendo alcuni problemi con l'allineamento variabile. Ho letto il manuale di gcc per __attribute__((aligned(4),packed)) interpreto ciò che viene detto come l'inizio della struct è allineato al boundry 4 byte e l'interno rimane intatta a causa della dichiarazione al sacco.

originariamente avevo questa ma a volte viene collocato non allineato con il limite di 4 byte.

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

quindi lo cambio a questo.

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;

La capire ho detto in precedenza sembra essere corretto in quanto sia la struct è ora allineato a un limite di 4 byte e ed i dati all'interno è ora allineato a un limite di quattro byte, ma a causa della endianess, la dimensione della struttura è aumentato in dimensioni da 42 a 44 byte. Questa dimensione è critica come abbiamo altre applicazioni che dipendono dal struct essere 42 byte.

Potrebbe qualche descrivermi come eseguire l'operazione che ho bisogno. Ogni aiuto è molto apprezzato.

È stato utile?

Soluzione

Se stai seconda sizeof(yourstruct) essere 42 byte, si sta per essere morso da un mondo di ipotesi non-portatili. Non hai detto ciò che questo è per, ma sembra probabile che l'endianness degli argomenti contenuti struct pure, così si può anche avere una mancata corrispondenza con l'x86 anche lì.

In questa situazione credo che l'unico modo sicuro per far fronte è quella di utilizzare unsigned char[42] nelle parti in cui è importante. Inizia scrivendo una specifica precisa di ciò che esattamente i campi sono dove in questo blocco 42 byte, e ciò che endian, quindi utilizzare tale definizione per scrivere del codice per tradurre tra questo e una struct è possibile interagire con. Il codice sarà probabilmente sia tutto-at-once codice di serializzazione (aka marshalling), o di un gruppo di getter e setter.

Altri suggerimenti

Questo è uno dei motivi per cui la lettura di interi struct invece di membro a membro non riesce, e dovrebbe essere evitato.

In questo caso, l'imballaggio più allineando a 4 significa che ci saranno due byte di riempimento. Questo accade perché la dimensione deve essere compatibile per la memorizzazione del tipo in un array con tutti gli oggetti ancora allineati a 4.

Immagino che tu abbia qualcosa di simile:

read(fd, &obj, sizeof obj)

Perché non vuoi leggere quei 2 byte di riempimento che appartengono a dati diversi, è necessario specificare le dimensioni in modo esplicito:

read(fd, &obj, 42)

Il che è possibile mantenere gestibile:

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

// ...

read(fd, &obj, obj.read_size)

In alternativa, se non è possibile utilizzare alcune funzioni del C ++ nella directory C:

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

// ...

read(fd, &obj, CHALLENGE_read_size)

Alla prossima occasione refactoring, vi consiglierei vivamente di iniziare a leggere ogni membro individuale, che può essere facilmente incapsulata all'interno di una funzione.

Qual è il tuo vero obiettivo?

Se è a che fare con i dati che è in un file o sul filo in un formato particolare che cosa si dovrebbe fare è scrivere su alcune routine di marshaling / serializzazione che muovono i dati tra lo struct compilatore che rappresenta come si vuole affrontare con la dati all'interno del programma e un array di caratteri che si occupa di come i dati appare sul / file di filo.

Quindi tutto ciò che deve essere affrontato con attenzione e, eventualmente, hanno codice specifico della piattaforma è la routine marshalling. E si può scrivere alcuni test di unità nice-n-brutto per garantire che i dati marshalling ottiene da e per la struct correttamente, non importa quale piattaforma si potrebbe avere a porta per oggi e in futuro.

Sono stato in movimento strutture avanti e indietro da Linux, Windows, Mac, C, Swift, Assembly, etc.

Il problema non è che non può essere fatto, il problema è che non si può essere pigri e deve capire i vostri strumenti.

Non vedo il motivo per cui non è possibile utilizzare:

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

possono usarlo e non richiede alcun codice speciale o intelligente. Scrivo un sacco di codice che comunica al braccio. Le strutture sono ciò che rende il lavoro le cose. __attribute__ ((packed)) è mio amico.

Le probabilità di essere in un "mondo di male" sono pari a zero se si capisce che cosa sta succedendo con entrambi.

Infine, non posso per la vita a capire come ottenere 42 o 44. Int è o 4 nostri 8 byte (a seconda del compilatore). Che mette il numero sia a 16 + 16 + 2 = 34 o 32 + 16 + 2 = 50 -. Assumendo che è veramente ricco

Come ho detto, conoscendo i vostri strumenti è parte del problema.

Direi che il problema è che 42 non è divisibile per 4, e in modo da ottenere fuori allineamento se mettete alcuni di questi le strutture back to back (ad esempio allocare memoria per molti di loro, determinare la dimensione con sizeof ). Avere la dimensione come 44 costringe l'allineamento in questi casi, come da voi richiesto. Tuttavia, se l'offset interno di ciascun membro struct rimane la stessa, si tratta lo struct 44 byte come se fosse di 42 byte (purché si prende cura di allineare eventuali questi dati al confine corretta).

Un trucco per cercare potrebbe essere messa sia di questi le strutture all'interno di un unico tipo di unione e utilizzare solo la versione 42-byte all'interno di ogni tale unione.

Come sto usando Linux, ho scoperto che da echo 3 > /proc/cpu/alignment esso mi emettere un avvertimento, e risolvere il problema di allineamento. Si tratta di un lavoro in giro, ma è molto utile con la localizzazione in cui le strutture non riescono a essere disallineati.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top