Effets de __attribute __ ((packed)) sur un tableau imbriqué de structures?

Le Problème

Je suis en train de travailler sur l'envoi d'une structure brute sur un réseau à un programme connu de l'autre côté, mais à vous soucier de l'silencieusement introduit la mémoire utilisée pour l'alignement des structures (d'autres problèmes comme l'endianness sont couverts). Ce que je suis en train de travailler avec quelque chose comme:

typedef struct __attribute__((packed))
{
   uint16_t field1;
   uint16_t field2;
   uint16_t field3;
} packed_1_s;

typedef struct __attribute__((packed))
{
   uint16_t fieldA;
   uint16_t fieldB;
   packed_1_s structArray[10];
} packed_2_s;

typedef struct __attribute__((packed))
{
   uint16_t fieldX;
   packed_2_s fieldY;
   uint8_t arrayZ[20];
} data_s;

Je comprends que, normalement, la packed_1_s structure pourrait/aurait plus d'espace alloué pour chaque instance de la structure à remplir pour le compilateur favori taille (dépend du matériel, il est en cours de construction pour), et qui a favorisé la taille peut être n'importe où à partir de 2 octets 64 octets (plus récemment). Normalement, si j'avais une seule instance de packed_1_s dans packed_2_s il n'y aurait pas de problème, mais je me suis fait comprendre il y a quelques différences lorsque vous essayez de mettre des éléments dans un tableau.

Tentatives De Solutions

La gcc documentation semble suggérer que simplement en incluant les paniers de l'attribut dans la packed_2_s définition, les champs, même si elles sont des tableaux, seront tout aussi serrés que possible et de ne pas ajouter de l'espace pour la packed_2_s structure pour aligner les éléments de la matrice. La documentation sur les aligner() attribut mais suggère que les tableaux sont traités différemment des autres domaines, et il faut les aligner/paniers attribut défini sur le domaine directement pour modifier l'espacement supplémentaire ajouté à correspondre au spécifié à l'alignement (ou son absence). J'ai essayé le réglage de la emballés attribut à la fois sur les tableaustruct terrain, et quand ça ne marche pas, fait un test en définissant les paniers attribut sur arrayZ dans le code ci-dessus:

packed_1_s structArray[10] __attribute__((packed));

uint8_t arrayZ[20] __attribute__((packed));

Les deux tentatives m'a donné un avertissement du compilateur que les paniers attribut n'était pas comprise dans ce contexte et ignorées (bonne chose-je construire avec le "Mur").

Je l'espère, un moyen de contourner le problème serait d'utiliser l'attribut align(1), ce qui indique un alignement souhaité de 1 octet, qui est comparable à la emballés attribut, mais la documentation dit que les aligner() attribut ne peut augmentation l'alignement et emballé doit être utilisé pour diminution l'alignement.

Considérations

De ce que je peux déterminer à partir de la GCC de la documentation, il semble comme il y a 3 causes majeures de la mémoire supplémentaire à insérer.

  1. Structure de contenu peut avoir de la mémoire supplémentaire alloué à l'
    la structure elle-même pour modifier l'espacement entre les champs.
    Effectivement, la définition de la carte mémoire de la structure
    contenu à l'intérieur de la structure peut changer (mais pas dans l'ordre
    des éléments).
  2. De Structures de la mémoire supplémentaire qui leur est alloué pour remplir
    pour plus efficaces dans l'ensemble de la taille. Ce n'est généralement
    l'intention de sorte que d'autres variables à venir après une déclaration de l'un des
    leur cas ne tombe pas dans le même "bloc", comme l'
    la structure de l'instance où un "bloc" est défini par le système/compilateur.
  3. Tableaux, que ce soit au sein d'une structure ou non, peut avoir d'autres
    mémoire ajoutés à déplacer les éléments à l'efficacité de l'alignement.

Aussi loin que je peux dire, les paniers attribut peut être utilisé pour modifier la structure et le bloc de la mémoire supplémentaire ajouté dans les cas 1 et 2 ci-dessus, mais il ne semble pas être un moyen pour gérer les cas 3 ci-dessus sur mon compilateur(s).

La Question

Est-il de toute façon à garantir que la data_s structure aura absolument aucun espace supplémentaire ajouté ou l'un quelconque de ses sous-structures, donc je n'ai pas de compilateur dépendante des changements dans la carte mémoire? Suis-je malentendu le cas où le compilateur peut insérer un espace, intentionnellement, maj de la carte mémoire?

MODIFIER

J'ai discuté de certains des problèmes avec mon gourou local et il semble que j'ai une certaine incompréhension de cas 3 ci-dessus. Les éléments du tableau n'avez pas l'espace à insérer entre eux, mais l'espace supplémentaire pour garantir qu'ils s'aligner correctement est ajouté à la structure elle-même. Apparemment, cela suggère des choses comme "sizeof(structureOnlyContaining_uint32_t)" ne permet pas toujours de retour "4" depuis l'espace supplémentaire peut être ajouté pour aligner les uint32_t type de données sur le compilateur utilisé. Le résultat est qu'il ya vraiment seulement 2 cas:

  1. Les grands décalages entre les champs de la mémoire de la carte de la structure.
    L'espace entre les champs peuvent être modifiés pour s'aligner chaque champ.
    Ceci peut être changé en utilisant les paniers ou les aligner() attributs.
  2. Structure de fin de remplissage. La taille d'une structure, telle qu'elle est renvoyée par
    sizeof(), peut être modifié afin de tableaux de structures en fin de
    correctement alignée pour le système. Cela permet à tous les systèmes d'assumer
    que le début de structures seront toujours alignés, à l'origine de problèmes
    s'ils ne le sont pas. Ce ne semble pas affectée par le pack ou aligner des attributs.

En raison des nouveaux cas 2, les éléments d'un tableau dans une structure n'est pas nécessairement obéir aux paniers ou aligner() attributs spécifiés sur la structure, bien que le début du tableau et le terrain immédiatement après le tableau n'.

Ma question est donc de savoir quoi faire avec la tableaustruct dans packed_2_s depuis la taille du tableau dans son ensemble ne peut être garanti que par les paniers de l'attribut. Est-il un moyen de garantir la taille fixe de la tableaustruct champ dans son ensemble? Il convient de noter que je ne peux pas augmenter la taille de la packed_1_s trop depuis le data_s struct doit être maintenue aussi faible que possible (son remplaçant données Audio/Vidéo en streaming scénario).

source d'informationauteur mtalexan | 2011-10-31