JVA*_*pen 7 c++ language-lawyer c++17
C ++ 17引入了用于过度对齐数据的动态内存分配
除了现有std::max_align_t的基本对齐方式之外,它还增加__STDCPP_DEFAULT_NEW_ALIGNMENT__了运营商新保证的最小对齐方式。
使用MSVC2017 64位编译时,这些常量std::max_align_t的大小为8 __STDCPP_DEFAULT_NEW_ALIGNMENT__,大小为16。
但是,如cppreference:运算符新的全局替换上所述,允许否决运算符new / free 。
查看所有文档,我不清楚是否允许该函数提供新的默认对齐方式,如果允许,则是否允许我们重新定义此常量。
举例说明:
#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;
}
Run Code Online (Sandbox Code Playgroud)
我之所以这样问,是因为我正在调查正在使用Clang编译的MSVC程序中的崩溃。在这里,我们注意到clang使用依赖于16位对齐的CPU指令来初始化大小为8的类。
根据N4659(C ++ 17的最新公开草案):
6.7.4p3:
C ++程序中定义的任何分配和/或释放函数,包括库中的默认版本,均应符合6.7.4.1和6.7.4.2中指定的语义。
6.7.4.1p2:
...返回的指针应适当对齐,以便可以将其转换为指向任何合适的完整对象类型(21.6.2.1)的指针,然后用于访问分配的存储中的对象或数组(直到显式释放该存储)通过调用相应的释放函数)。...
19.8p1:
以下宏名称应由实现定义:...
__STDCPP_DEFAULT_NEW_ALIGNMENT__std :: size_t类型的整数文字,其值是通过调用operator new(std::size_t)或保证的对齐方式operator new[](std::size_t)。...
19.8p4:
如果此子节中的任何预定义宏名称或标识符
defined是#define或#undef预处理指令的主题,则该行为未定义。...
因此,您无法__STDCPP_DEFAULT_NEW_ALIGNMENT__在程序中更改该值,并且如果alignas(__STDCPP_DEFAULT_NEW_ALIGNMENT__)为大小8的类型调用了分配函数,则无法检测到该值,但是您仍然需要返回适当对齐的指针。
但是,您可以__STDCPP_DEFAULT_NEW_ALIGNMENT__使用-fnew-alignment编译器选项更改clang自身定义的值。不确定是否对您有帮助。