新的重载运算符,具有较小的默认对齐方式

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的类。

Kit*_*it. 5

根据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自身定义的值。不确定是否对您有帮助。