C ++ 17 введено Динамическое выделение памяти для выровненных данных
Помимо существующего std::max_align_t
фундаментального выравнивания, оно добавило __STDCPP_DEFAULT_NEW_ALIGNMENT__
минимальное выравнивание, которое операторновые гарантии.
При 64-битной компиляции MSVC2017 эти константы приводят к std::max_align_t
размера 8 и __STDCPP_DEFAULT_NEW_ALIGNMENT__
размера 16.
Однако разрешено отменять оператор new / free, как упоминалось в cppreference: operator new - глобальные замены .
Глядя на все документы, мне неясно, разрешено ли этой функции предоставлять новое выравнивание по умолчанию, и если да,если нам разрешено переопределить эту константу.
Пример для иллюстрации:
#include <new>
#include <iostream>
#include <cassert>
#include <cstdint>
#include <cstddef>
static_assert(alignof(std::max_align_t) == 8);
static_assert(__STDCPP_DEFAULT_NEW_ALIGNMENT__ == 16);
void * operator new(size_t size)
{
std::cout << "New operator overloading " << std::endl;
void * p = std::malloc((size == 8) ? 16 : size);
assert(std::uintptr_t(p)%16 == 0);
if (size == 8)
{
auto correctedPtr = std::uintptr_t(p) + 8;
return (void*)correctedPtr;
}
return p;
}
void operator delete(void * p)
{
std::cout << "Delete operator overloading " << std::endl;
if (std::uintptr_t(p)%16 != 0)
{
auto correctedPtr = std::uintptr_t(p) - 8;
std::free((void*)correctedPtr);
}
std::free(p);
}
namespace
{
struct D
{
double d;
};
}
int main(int, char**)
{
new D{};
return 0;
}
Код в проводнике компилятора
Причина, по которой явопрос в том, что я расследую сбои в программе MSVC, которая сейчас компилируется с Clang.Здесь мы заметили, что clang использует инструкции процессора, которые полагаются на это 16-битное выравнивание, чтобы инициализировать класс размера 8.