像_alloca一样在堆栈上分配对齐的内存

时间:2017-10-22 20:40:14

标签: c++ memory-management c++17 c11 alloca

_alloca()的文档说here

  

_alloca例程返回指向已分配空间的void指针,   保证适当地对齐以存储任何类型的   对象

然而,here它说:

  

_alloca需要16字节对齐,并且还需要使用帧指针。

所以看来在第一个参考文献中他们忘记了32字节对齐的AVX / AVX2类型,如__m256d

让我感到困惑的另一件事是第一页说_alloca()已被弃用,而它建议使用一个可以从堆而不是堆栈分配内存的函数(这在我的多线程中是不可接受的)应用程序)。

那么有人能指出我是否有一些现代的(可能是新的C / C ++标准?)方式来进行对齐的堆栈内存分配?

澄清1 :请不要提供需要数组大小为编译时常量的解决方案。我的函数根据运行时参数值分配可变数量的数组项。

4 个答案:

答案 0 :(得分:4)

使用_alloca()进行总体定位,然后手动对齐。像这样:

const int align = 32;
void *p =_alloca(n + align - 1);
__m256d *pm = (__m256d *)((((int_ptr_t)p + align - 1) / align) * align);

如有必要,请将const替换为#define

答案 1 :(得分:1)

C ++ 11引入了alignof运算符:

  

alignof表达式产生其操作数类型的对齐要求。

您可以按如下方式使用它:

struct s {};
typedef s __attribute__ ((aligned (64))) aligned_s;

std::cout << alignof(aligned_s); // Outputs: 64

注意:如果类型的对齐方式大于其大小,编译器将不允许您声明数组类型的数组(请参阅更多here):

  

错误:数组元素的对齐大于元素大小

但是,如果您的类型的对齐方式小于其大小,则可以 安全地分配数组:

aligned_s arr[32];
-- OR --
constexpr size_t arr_size = 32;
aligned_s arr[arr_size];

支持VLA的编译器也允许使用新定义类型的编译器。

答案 2 :(得分:1)

&#34;现代&#34;方式是:

Don't make variable-length allocation on the stack.

在你的问题的上下文中 - 想要在堆上进行分配而不是这样做 - 我假设你可能正在分配超过一些小的编译时常量内存。在这种情况下,您只需使用alloca()电话粉碎您的筹码即可。而是使用线程安全的内存分配器。我确定在GitHub上有这样的库(在最坏的情况下,你可以使用全局互斥锁来保护分配调用,但如果你需要大量的互斥锁,它会很慢)。

另一方面,如果你事先知道分配大小的上限 - 只需在线程本地存储中预先分配那么多内存;或使用固定大小的本地数组(将在堆栈上分配)。

答案 3 :(得分:1)

_alloca()当然不是处理堆栈对齐的标准或可移植方式。幸运的是,在C ++ 11中,我们获得了alignasstd::aligned_storage。这些都没有强迫你把任何东西放在堆上,所以它们应该适用于你的用例。例如,要将结构数组对齐到32字节边界:

#include <type_traits>

struct bar { int member; /*...*/ };
void fun() {
  std::aligned_storage<sizeof(bar), 32>::type array[16];
  auto bar_array = reinterpret_cast<bar*>(array);
}

或者,如果您只想将堆栈上的单个变量与边界对齐:

void bun() {
  alignas(32) bar b;
}

您还可以使用alignof运算符来获取给定类型的对齐要求。