Pourquoi mon élément de structure porte-t-il des octets de remplissage?

J’ai un comportement déroutant avec l’alignement de la mémoire des éléments de structure. Considérez ces deux structures:

typedef struct s_inner { unsigned long ul1; double dbl1; fourth_struct s4; unsigned long ul2; int i1; } t_inner; typedef struct s_outer { other_struct member1; /* 4-byte aligned, 40 bytes in terms of sizeof() */ unsigned long member2; t_inner member3; /* see above */ } t_outer; 

Lorsque j’inspecte la structure de la mémoire de t_outer, je constate que les éléments de member1 sont alignés sur 4 octets, exactement comme je l’ member1 . La disposition de la mémoire de member3 est également member3 celle attendue: ul1 a 4 octets de remplissage attachés de sorte que dbl1 est aligné sur une bordure de 8 octets (normal sur Win32).

Cependant, lorsque member2 structure de mémoire de member2 , je constate que ce membre est associé à 4 octets de remplissage. Quelqu’un pourrait-il expliquer pourquoi, sur Terre, member2 reçoit des octets de remplissage? Mon attente était que le member2 ne porte pas de rembourrage.


Edit 1: Voir cette image mémoire. Avant de remplir les éléments de structure, memset la structure entière du t_outer avec les p :

  • la zone rouge est member1
  • la zone bleue est member2
  • la zone verte est member3
  • la zone jaune marque l’emplacement de dbl1 dans member3

mise en page mémoire


Contraintes

  • Le compilateur est VS2012
  • la other_struct réelle de other_struct ne devrait pas avoir d’importance ici, c’est une structure alignée sur 4 octets de taille 40 octets
  • Je ne veux aucune solution de contournement pour le comportement (réorganisation, emballage, …) mais une explication de la raison pour laquelle cela se produit.

de sorte que dbl1 est aligné sur une bordure de 8 octets

Sûr. Mais cette garantie d’alignement signifie bupkis si la structure elle-même n’est pas alignée sur 8 également. Ce qui est une garantie fournie normalement par les choix d’adresse du compilateur pour la section de données et le cadre de stack. Ou l’allocateur de mémoire. Tous garantissent au moins un alignement à 8.

Mais lorsque vous intégrez la structure dans s_outer, ces 4 octets de remplissage avant member3 (et non après member2) sont nécessaires pour récupérer la garantie d’alignement.

Notez également qu’une structure peut avoir un remplissage après le dernier membre. Ce qui peut être nécessaire pour s’assurer que les membres sont toujours alignés lorsque la structure est stockée dans un tableau. Même raison.

Les documents VS2012 décrivent son comportement de remplissage . En particulier, ils spécifient que l’exigence d’alignement pour une struct est la plus grande exigence d’alignement de l’un de ses membres. Le type t_inner membre t_inner a un membre du type double , avec une exigence d’alignement de 8 octets; par conséquent, le member3 globalement une exigence d’alignement de 8 octets (et t_outer a également une exigence d’alignement de 8 octets). Un rembourrage est requirejs entre member2 et member3 pour obtenir un alignement de 8 octets de l’ member3 .