Does the standard require that objects in automatic storage have the correct alignment for any type (for example, how does malloc do this)?

I am wondering if allocating the buffer on the stack requires the correct alignment for any type, similar to how malloc works, or if I have to use something like std::aligned_storage .

Consider the following code block:

 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<std::wstring> RegistryKey::EnumerateValueNames() const { std::vector<std::wstring> 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<KEY_VALUE_BASIC_INFORMATION const*>(buff); for(;;) { ULONG resultLength; NTSTATUS errorCheck = PNtEnumerateValueKeyFunc( hKey_, index++, KeyValueBasicInformation, buff, valueNameStructSize, &resultLength); if (NT_SUCCESS(errorCheck)) { result.emplace_back(std::wstring(basicValueInformation->Name, basicValueInformation->NameLength / sizeof(wchar_t))); } else if (errorCheck == STATUS_NO_MORE_ENTRIES) { break; } else { Win32Exception::ThrowFromNtError(errorCheck); } } return result; } 

Notice how buff is a character buffer pushed onto the stack to hold a given maximum amount of data. However, I am concerned that the cast needed to interpret the buffer as a string may result in an alignment error if this code needs to be ported to another platform (e.g. ARM or IA64).

EDIT: If anyone is interested, I will redo this with std::aligned_storage and std::alignment_of :

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

There are no requirements in the standard for aligning automatic variables (or variables with static storage, for that matter), except that the compiler must make sure that their access works.

  • C ++ 03 3.9 / 5 Types

Object types have alignment requirements (3.9.1, 3.9.2). alignment of the full type of an object is an implementation-defined integer value representing the number of bytes; the object is allocated at the address corresponding to the alignment requirements of its object type

Note. "Object type" here means a type that is not a function, reference, or void type (i.e. applies to unsigned char ).

One way to get a flush buffer is to declare buff as follows:

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

And you can get rid of reinterpret_cast<> for download.

+5
source

All Articles