c++ - 如何强制对齐堆分配的对象?

标签 c++ c++11 memory-alignment

How use alignof to force alignment for a heap allocation? ,我询问了如何将 alignof 用于堆分配的对象。现在我将我的问题归纳为任何强制堆分配对象对齐的方法,因为我找不到使用 alignof 的方法, std::aligned_storagestd::align。以下代码可以编译,但 VC12 和 Clang 3.2 都不会生成零序列作为输出,这表明我的对齐请求得到了尊重。 (gcc 4.8.1 缺少 std::align,但如果您注释掉该部分,代码将在 gcc 4.8.1 下编译并生成表明我的对齐请求被忽略的输出。)

#include <iostream>
#include <memory>

int main()
{
  // Try using alignas on the allocation
  {
    class Widget {};

    for (int i = 0; i < 5; ++i)
      {
        auto ptr = new alignas(64) Widget;
        std::cout << (long)ptr % 64 << '\n';    // should be 0
      }
  }

  // Try using alignas on the type
  {
    class alignas(64) Widget {};

    for (int i = 0; i < 5; ++i)
      {
        auto ptr = new Widget;
        std::cout << (long)ptr % 64 << '\n';    // should be 0
      }
  }

  // Try using std::aligned_storage
  {
    class Widget {};

    using WidgetStorage_t = 
      std::aligned_storage<sizeof(Widget), 64>::type;

    for (int i = 0; i < 5; ++i)
      {
        auto ptr = new WidgetStorage_t;         // get buffer
        new (ptr) Widget;                       // construct Widget
        std::cout << (long)ptr % 64 << '\n';    // should be 0
      }
  }

  // Try using operator new + std::align
  {
    class Widget {};

    for (int i = 0; i < 5; ++i)
      {
        auto requestSize =      // double space to ensure that a
          2 * sizeof(Widget);   // Widget fits after ptr adjustment

        auto ptr = operator new(requestSize);   // get buffer

        std::align(64, sizeof(Widget),          // align ptr 
                   ptr, requestSize);           // inside buffer

        new (ptr) Widget;                       // construct Widget

        std::cout << (long)ptr % 64 << '\n';    // should be 0
      }
  }
}

更新:上面我用于测试 std::align 的代码不正确。以下替换代码有效:

 // Try using operator new + std::align
  {
    class Widget {};

    for (int i = 0; i < 5; ++i)
      {
        auto requestSize =       // ensure that a
          sizeof(Widget) + 64;   // Widget fits after ptr adjustment

        auto ptr = operator new(requestSize);   // get buffer

        std::align(64, sizeof(Widget),          // align ptr 
                   ptr, requestSize);           // inside buffer

        new (ptr) Widget;                       // construct Widget

        std::cout << (long)ptr % 64 << '\n';    // should be 0
      }
  }

这是完成工作的唯一方法吗?它比我想要的要复杂得多,因为现在必须跟踪两个指针:指向对象的已调整指针(销毁构造对象所必需的)和指向内存缓冲区的未调整指针(释放所必需的)内存)。

最佳答案

我在实践中看到的一个选择是过度分配,然后自行调整。

例如,假设您要分配 N 字节,与 M 字节边界对齐。您可以继续分配 N+M-1 字节,然后在分配的空间中找到第一个 M 字节对齐的地址。例如,您可以执行以下操作:

const size_t N = sizeof(Widget);
const size_t M = 64;
char *pc = new char[N+M-1];
char *pc_aligned = (pc+M-1)&(~(M-1));
Widget *p = new (pc_aligned) Widget();    // placement new
// ...
p->~Widget();                             // explicitly call destructor
delete [] pc;                             // delete array allocated with new

关于c++ - 如何强制对齐堆分配的对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21896311/

相关文章:

C++ 无法让 cin 从文件重定向中读取结束行字符

c++ - 在 C++ 和排序中使用原子的乐观锁定策略

c++ - 编程风格 : when to add a variable?

javascript - C++11 std::regex_replace() 创建带有特定字符串问题的正则表达式

c - 将 sbrk 的结果分配给指针时的对齐问题 - K&R

c - 读取为未缓存的直接 I/O 打开的文件的最后一个 block 不会产生 EOF,正常行为?

c++ - Juno CDT 插件无法运行 C++ 应用程序

c++ - 在为标准模板函数创建仿函数对象时减少样板

c++ - 如何编译 Hinnant 的 short_alloc 分配器