【问题标题】:alignas keyword not respected不尊重 alignas 关键字
【发布时间】:2016-05-23 18:44:50
【问题描述】:

我想在缓存边界上过度对齐我的类型,所以我使用了alignas

struct alignas(64) W { };

这编译得很好。但是,令我惊讶的是,当我尝试分配一堆 Ws 时,它们不是 64 字节对齐的,而是实际上是 16 字节对齐的:

#include <iostream>
#include <iomanip>
#include <unordered_map>

struct alignas(64) W { };

int main() {
    std::unordered_map<int, int> offset;

    for (int i = 0; i < 1000; ++i) {
        auto w = new W;
        offset[(uintptr_t)w % 64]++;
    }   

    for (const auto& p : offset) {
        std::cout << p.first << ' ' << p.second << '\n';
    }   
}

产量:

0 250
16 250
32 250
48 250

在多个编译中(gcc 4.8.2、gcc 5.2.0、clang 3.7.1)。这是怎么回事?我告诉它对齐,为什么它不对齐?

【问题讨论】:

  • @T.C.这看起来应该是一个答案。
  • operator new 是 borken,编译器知道对齐要求,但无法告诉 operator。所以这几乎肯定会出错。解决它是你的负担,比如aligned_alloc() 或posix_memalign() 或_aligned_malloc()。
  • 是的,编译器可以控制它,它会选择堆栈偏移量。
  • @HansPassant 要添加到该建议,您可能可以在 struct W 内部创建一个 operator newoperator delete,在内部调用 aligned_allocaligned_free 而不会使外部客户的工作复杂化

标签: c++ c++11 alignas


【解决方案1】:

另一个答案是正确的,因为它解释了现有的限制,但我想指出,情况即将好转。

如 T.C. 所示。在 cmets 中,这是语言中长期存在的缺陷。 looksthe WG effort 一样解决此问题已导致 C++17 中的解决方案(刚刚达到功能完整状态)。因此,当编译到该标准时,通过使用new 的新std::align_val_t 重载,动态分配最终将遵守过度对齐。从而解决巴里的问题!

鉴于所需的新脚手架数量,我认为这不会向后移植到标准的早期版本,因此关于动态分配的旧警告仅适用于具有基本对齐的类型可能会保持真实。

【讨论】:

    【解决方案2】:

    这里得到了很好的回答:https://stackoverflow.com/a/16510895

    基本上:new(至少在其正常使用中)只保证每次调用 new 时保持恒定的最大对齐 (alignof(std::max_align_t))。

    【讨论】:

      猜你喜欢
      • 2020-06-03
      • 2014-11-11
      • 2011-10-26
      • 2020-10-10
      • 2020-10-11
      • 1970-01-01
      • 2019-08-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多