c++ - 使用较小的默认对齐重载新运算符
问题描述
C++17为过度对齐的数据引入了动态内存分配
除了现有std::max_align_t
的基本对齐之外,它还添加__STDCPP_DEFAULT_NEW_ALIGNMENT__
了 operator new 保证的最小对齐。
使用 MSVC2017 64 位编译,这些常量导致std::max_align_t
大小为 8 和__STDCPP_DEFAULT_NEW_ALIGNMENT__
大小为 16。
但是,如cppreference: operator new - global replacements中所述,它可以否决 operator 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;
}
我问这个的原因是因为我正在调查一个现在用 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)
or保证的对齐operator new[](std::size_t)
。...
19.8p4:
如果本子条款中的任何预定义宏名称或标识符
defined
是 a#define
或#undef
预处理指令的主题,则行为未定义。...
因此,您无法更改__STDCPP_DEFAULT_NEW_ALIGNMENT__
程序中的值,并且如果您的分配函数被调用为alignas(__STDCPP_DEFAULT_NEW_ALIGNMENT__)
大小为 8 的类型,您无法检测到这一点,但您仍然需要返回一个适当对齐的指针。
尽管如此,您可以使用编译器选项更改__STDCPP_DEFAULT_NEW_ALIGNMENT__
clang 本身定义的值。-fnew-alignment
不确定它是否对您的情况有帮助。
推荐阅读
- excel - 无法解决 VBA 数组错误 13 类型不匹配
- node.js - 如何使用驱动程序管理客户端加密数据密钥?
- angular - Angular NgFor 总是从输入的对象中获取最后一个值
- vim - 如何在 Vim 缓冲区中找到“<html>”?
- shopify - 无需 Shopify 应用程序即可在 Shopify 中自动导出自定义报告
- google-colaboratory - Colab 经常断开连接
- vue.js - Vue 组件数据对象属性的行为不符合预期 [已解决]
- reactjs - 如何将一个组件中查询的数据传递给另一个组件以用作查询变量?
- angular - 从服务器端接收多个通知
- angular - Datepicker 没有弹出 ng-bootstrap