如何强制 new 运算符返回的指针为 32 字节对齐
How to force pointer returned by new operator to be 32-byte aligned
我在我的程序中使用了 AVX2 intrinsic,并在 class 之一中声明了一个 __m256i 变量,如下所示:
class A {
protected:
__m256i buffer;
public:
A() {
buffer = _mm256_setzero_si256();
}
};
当我创建一个A的实例时,如果buffer的内存位置不是32字节对齐的,我得到一个Seg Fault。有没有办法强制 new 运算符的 return 地址或缓冲区的内存地址为 32 字节对齐?
您可以尝试使用 对齐说明符
class A {
protected:
__m256i alignas(32) buffer;
...
};
参见 C++ 标准的 §7.6.2。
根据评论,alignas
说明符似乎不起作用:
大多数编译器都有内置的对齐分配函数,比如GCC的aligned_alloc
。此函数可以与放置 new
运算符结合使用以创建对齐的对象实例。
例如:
void* ptr = aligned_alloc(32, sizeof(A));
A* a = new(ptr) A;
注意:使用放置new
需要手动调用析构函数,使用delete
不行
我认为你不需要新的展示位置:
#include <cstdlib>
#include <new>
using size_t = ::std::size_t;
template <size_t ALIGNMENT>
struct alignas(ALIGNMENT) AlignedNew {
static_assert(ALIGNMENT > 0, "ALIGNMENT must be positive");
static_assert((ALIGNMENT & (ALIGNMENT - 1)) == 0,
"ALIGNMENT must be a power of 2");
static_assert((ALIGNMENT % sizeof(void*)) == 0,
"ALIGNMENT must be a multiple of sizeof(void *)");
static void* operator new(size_t count) { return Allocate(count); }
static void* operator new[](size_t count) { return Allocate(count); }
static void operator delete(void* ptr) { free(ptr); }
static void operator delete[](void* ptr) { free(ptr); }
private:
static void* Allocate(size_t count) {
void* result = nullptr;
const auto alloc_failed = posix_memalign(&result, ALIGNMENT, count);
if (alloc_failed) throw ::std::bad_alloc();
return result;
}
};
现在只需继承AlignedNew<32>
。
另请参阅此提案,该提案已被 C++17 接受:Dynamic memory allocation for over-aligned data。
我在我的程序中使用了 AVX2 intrinsic,并在 class 之一中声明了一个 __m256i 变量,如下所示:
class A {
protected:
__m256i buffer;
public:
A() {
buffer = _mm256_setzero_si256();
}
};
当我创建一个A的实例时,如果buffer的内存位置不是32字节对齐的,我得到一个Seg Fault。有没有办法强制 new 运算符的 return 地址或缓冲区的内存地址为 32 字节对齐?
您可以尝试使用 对齐说明符
class A {
protected:
__m256i alignas(32) buffer;
...
};
参见 C++ 标准的 §7.6.2。
根据评论,alignas
说明符似乎不起作用:
大多数编译器都有内置的对齐分配函数,比如GCC的aligned_alloc
。此函数可以与放置 new
运算符结合使用以创建对齐的对象实例。
例如:
void* ptr = aligned_alloc(32, sizeof(A));
A* a = new(ptr) A;
注意:使用放置new
需要手动调用析构函数,使用delete
不行
我认为你不需要新的展示位置:
#include <cstdlib>
#include <new>
using size_t = ::std::size_t;
template <size_t ALIGNMENT>
struct alignas(ALIGNMENT) AlignedNew {
static_assert(ALIGNMENT > 0, "ALIGNMENT must be positive");
static_assert((ALIGNMENT & (ALIGNMENT - 1)) == 0,
"ALIGNMENT must be a power of 2");
static_assert((ALIGNMENT % sizeof(void*)) == 0,
"ALIGNMENT must be a multiple of sizeof(void *)");
static void* operator new(size_t count) { return Allocate(count); }
static void* operator new[](size_t count) { return Allocate(count); }
static void operator delete(void* ptr) { free(ptr); }
static void operator delete[](void* ptr) { free(ptr); }
private:
static void* Allocate(size_t count) {
void* result = nullptr;
const auto alloc_failed = posix_memalign(&result, ALIGNMENT, count);
if (alloc_failed) throw ::std::bad_alloc();
return result;
}
};
现在只需继承AlignedNew<32>
。
另请参阅此提案,该提案已被 C++17 接受:Dynamic memory allocation for over-aligned data。