Мне любопытно, требуется ли для правильного выравнивания для любого типа выделение буфера в стеке, аналогично тому, как работает malloc
, или если мне придется использовать что-то вроде std::aligned_storage
.
Рассмотрим следующий блок кода:
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;
}
Обратите внимание, как значение buff
представляет собой буфер символов, помещенный в стек, размер которого соответствует данному максимальному объему данных.Однако я обеспокоен тем, что приведение, требуемое для интерпретации буфера как строки, может вызвать ошибку выравнивания, если этот код будет перенесен на другую (скажем, ARM или IA64) платформу.
РЕДАКТИРОВАТЬ: Если кому-то интересноЯ переделал это в терминах std::aligned_storage
и 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);
}