Partager via


Problèmes d’empaquetage du compilateur C

Les niveaux d’empaquetage affectent la disposition de la mémoire des types pour MIDL et le compilateur Microsoft C/C++ de la même manière. Dans les environnements de build Microsoft, tels que l’environnement de build défini par VC++ ou le Kit de développement logiciel (SDK) de plateforme, le niveau d’empaquetage par défaut pour les compilateurs MIDL et C/C++ est le même ; le niveau d’empaquetage par défaut pour les environnements de génération Windows 32 bits et 64 bits est 8.

Alignement naturel

Pour les types en mémoire, l’alignement par défaut est le même que son alignement naturel.

  • Un type de base, tel que short, float et __int64, et un pointeur est aligné naturellement si sa représentation commence à une adresse modulo sa taille. Tous les types de base actuellement pris en charge ont des tailles de 1, 2, 4 ou 8. Les pointeurs ont une taille de 4 dans les environnements 32 bits et de 8 dans les environnements 64 bits.
  • Un type composé est aligné naturellement si chacun de ses composants est aligné naturellement par rapport au début du type et s’il n’y a pas d’écarts inutiles (remplissage) entre les composants. Les composants composés, tels que les champs ou les éléments, sont récursés en composants de type pointeur ou de type base.

Une règle simple pour vous aider à mémoriser ce comportement est que l’alignement naturel d’un type est égal aux plus grands alignements de ses composants.

Il existe une connexion entre l’alignement et la taille de mémoire d’un type dans des langages comme C ou C++ et IDL, tels qu’exprimés par l’opérateur sizeof(). La taille est un multiple de l’alignement (le multiple minimal couvrant le type). Cela provient d’une représentation de tableau en mémoire.

L’alignement naturel est important, car l’accès aux données mal alignées peut entraîner une exception sur certains systèmes. Les données peuvent être marquées pour une manipulation sécurisée en cas d’alignement incorrect, mais cela implique généralement une pénalité de vitesse qui peut être importante sur certaines plateformes.

Notes

En mémoire, les objets de types avec un alignement naturel de n sont garantis pour être correctement alignés lorsqu’ils sont placés à des adresses qui sont un multiple de n.

 

Empaquetage et alignement

La spécification d’un niveau d’emballage supérieur à l’alignement naturel d’un type ne modifie pas l’alignement du type. La spécification d’un niveau d’emballage inférieur à l’alignement naturel réduit l’alignement du type au niveau d’emballage. Par conséquent, les types emballés peuvent être placés en mémoire à des adresses qui sont un multiple du niveau d’emballage (l’alignement réduit) sans provoquer un mauvais alignement. Cela affecte à la fois les types simples et les types de composants. Pour les types composés, la disposition interne du type peut être affectée, car l’alignement réduit des composants peut modifier la taille du remplissage nécessaire pour l’alignement correct des composants, réduisant ainsi la taille du type.

Une règle simple pour vous aider à mémoriser ce comportement est que le nouvel alignement d’un type empaqueté est le plus petit du niveau d’emballage et son alignement naturel. La taille du type est un multiple du nouvel alignement. L’opérateur sizeof() retourne la taille réduite pour les types packed.

Par exemple, avec le niveau d’emballage 2, un long devient aligné à 2, et peut donc être placé à n’importe quelle adresse paire, pas seulement aux adresses qui sont un multiple de 4 comme ce serait le cas avec l’alignement naturel. Une structure avec un court et un long, empaquetés à 2, n’a pas besoin de l’écart interne entre le court et le long suivant qui était nécessaire pour l’alignement naturel; par conséquent, non seulement la structure est désormais alignée à 2, mais elle a également sa taille réduite de 8 à 6.

Par exemple, considérez un type composé constitué d’un caractère de 1 octet, d’un entier de 4 octets et d’un caractère de 1 octet :

struct mystructtype 
{    
    char c1;  /* requires 1 byte  */
              /* 3 bytes of padding with natural alignment only */
    long l2;  /* requires 4 bytes */
    char c3;  /* requires 1 byte  */
              /* 3 bytes of padding with natural alignment only */
 } mystruct;

Cette structure est naturellement alignée à 4 et a la taille naturelle de 12.

Pour le niveau d’emballage 4 ou supérieur, la structure mystruct est alignée sur 4 et sizeof(struct mystructtype) est égale à 12. La structure sera mal alignée si elle se trouve dans la mémoire à une adresse qui n’est pas un multiple de 4.

Pour le niveau d’emballage 2, la structure est alignée sur 2 et sa taille est de 8. La structure emballée avec le niveau 2 sera mal alignée si elle se trouve dans la mémoire à une adresse qui n’est pas un multiple de 2.

Pour le niveau d’emballage 1, la structure est alignée sur 1 et sa taille est de 6. La structure emballée avec le niveau 1 peut être placée n’importe où sans provoquer une erreur d’alignement.

/Zp

/Pack