La norme exige-t-elle que les objects stockés automatiquement aient le bon alignement pour tout type (par exemple, comme malloc)?

Je suis curieux de savoir si l’allocation d’un tampon sur la stack est nécessaire pour avoir un alignement correct pour tout type, similaire au fonctionnement de malloc , ou si je serais obligé d’utiliser quelque chose comme std::aligned_storage .

Considérons le bloc de code suivant:

 typedef enum _KEY_VALUE_INFORMATION_CLASS { KeyValueBasicInformation = 0, // Others } KEY_VALUE_INFORMATION_CLASS; typedef struct _KEY_VALUE_BASIC_INFORMATION { ULONG TitleIndex; ULONG Type; ULONG NameLength; WCHAR Name[1]; } KEY_VALUE_BASIC_INFORMATION, *PKEY_VALUE_BASIC_INFORMATION; std::vector RegistryKey::EnumerateValueNames() const { std::vector result; ULONG index = 0; const ULONG valueNameStructSize = 16384 * sizeof(wchar_t) + sizeof(KEY_VALUE_BASIC_INFORMATION); // Stack buffer here unsigned char buff[valueNameStructSize]; // Casted here KEY_VALUE_BASIC_INFORMATION const* basicValueInformation = reinterpret_cast(buff); for(;;) { ULONG resultLength; NTSTATUS errorCheck = PNtEnumerateValueKeyFunc( hKey_, index++, KeyValueBasicInformation, buff, valueNameStructSize, &resultLength); if (NT_SUCCESS(errorCheck)) { result.emplace_back(std::wssortingng(basicValueInformation->Name, basicValueInformation->NameLength / sizeof(wchar_t))); } else if (errorCheck == STATUS_NO_MORE_ENTRIES) { break; } else { Win32Exception::ThrowFromNtError(errorCheck); } } return result; } 

Notez que la valeur buff est un tampon de caractères placé sur la stack, dimensionné pour contenir une quantité maximale de données. Cependant, je m’inquiète du fait que la dissortingbution requirejse pour interpréter le tampon en tant que chaîne peut provoquer une erreur d’alignement si ce code devait être porté sur une autre plate-forme (par exemple, ARM ou IA64).

EDIT: Si quelqu’un est curieux, j’ai refait cela en termes de std::aligned_storage et std::alignment_of :

 std::vector RegistryKey::EnumerateValueNames() const { std::vector result; ULONG index = 0; const ULONG valueNameStructSize = 16384 * sizeof(wchar_t) + sizeof(KEY_VALUE_BASIC_INFORMATION); std::aligned_storage<valueNameStructSize, std::alignment_of::value>::type buff; auto basicValueInformation = reinterpret_cast(&buff); for(;;) { ULONG resultLength; NTSTATUS errorCheck = PNtEnumerateValueKeyFunc( hKey_, index++, KeyValueBasicInformation, basicValueInformation, valueNameStructSize, &resultLength); if (NT_SUCCESS(errorCheck)) { result.emplace_back(std::wssortingng(basicValueInformation->Name, basicValueInformation->NameLength / sizeof(wchar_t))); } else if (errorCheck == STATUS_NO_MORE_ENTRIES) { break; } else { Win32Exception::ThrowFromNtError(errorCheck); } } return std::move(result); } 

La norme n’impose aucune exigence sur l’alignement des variables automatiques (ou des variables avec stockage statique), sauf que le compilateur doit s’assurer que leur access fonctionne.

  • C ++ 03 3.9 / 5 Types

Les types d’object ont des exigences d’alignement (3.9.1, 3.9.2). L’alignement d’un type d’object complet est une valeur entière définie par la mise en œuvre représentant un nombre d’octets; un object est alloué à une adresse qui répond aux exigences d’alignement de son type d’object

Note: “type d’object” signifie ici un type qui n’est pas une fonction, une référence ou un type vide (c’est-à-dire qu’il s’applique aux caractères unsigned char ).

Une façon d’obtenir un tampon aligné pourrait consister à déclarer buff comme buff :

 KEY_VALUE_BASIC_INFORMATION buff[valueNameStructSize/sizeof(KEY_VALUE_BASIC_INFORMATION) + 1]; 

Et vous pourrez vous débarrasser de reinterpret_cast<> pour démarrer.