【问题标题】:optimization based on alignment requirements基于对齐要求的优化
【发布时间】:2018-04-01 11:32:20
【问题描述】:

根据[basic.align]

对象类型有对齐要求([basic.fundamental], [basic.compound]) 对地址进行限制 可以分配该类型的对象。

我希望 C++ 编译器可以假定任何指向 T 的指针都指向正确对齐的 T。

例如(如果 alignof(int) == 4)

int* p = /* ... */
auto val = p[0];
if ((reinterpret_cast<std::uintptr_t>(p) & 3) != 0) {
   // assumed to be unreachable
}

但是,在编译器资源管理器中测试 GCC 和 clang,我没有看到他们中的任何一个做出这个假设。 即使我取消引用指针(如果它没有正确对齐肯定会导致 UB)这个指针值假设是不成立的。

我认识到指针到整数值的映射是实现定义的,并且编译器可能有一个不同于这段代码假设的映射(尽管我不这么认为)。

我还认识到,做出这种假设可能会破坏生产中的大量代码,并解释为什么这些编译器目前没有这样做。

我的问题是:根据标准,编译器可以做出有效的假设吗?

如果不是,请引用标准!

编辑:澄清指针被取消引用。

EDIT2:说 alignof()(而不是 sizeof())

【问题讨论】:

  • 标准不禁止使用指针对齐位存储自定义数据。
  • 我不明白这有什么关系。当然,您不能取消引用错误对齐的指针,因此您必须在使用指针之前屏蔽这些位
  • 我认为根本的根本问题是——错位访问真的是 UB 还是实现定义的?
  • 我不认为这是有争议的。 undefined-sanitizer (ubsan) 检查未对齐的访问,有这样的:pzemtsov.github.io/2016/11/06/bug-story-alignment-on-x86.html
  • 编译器不需要使用任何允许做出的任意假设

标签: c++ language-lawyer compiler-optimization memory-alignment


【解决方案1】:

是的,编译器可能假定指针正确对齐。

让我们暂时假设有一个函数is_aligned,它测试指针指向的地址是否与其类型正确对齐。

int* p = /* ... */
auto val = p[0];
if (is_aligned(p)) {
   // assumed to be unreachable
}

然后会是真的。我们从[basic.life] 推断出这一点

T 类型对象的生命周期开始于:

  • 已获得具有适合 T 类型的正确对齐和大小的存储 [...]

因此不存在不正确对齐的对象。 It then follows 该指针要么是空指针,要么是无效指针,要么是指向另一个类型的对象。

通过空指针访问是非法的,access through invalid pointers 也是非法的,access to an object of another type 也是非法的,这使得通过未对齐的指针 UB 进行访问。

unsigned charcharstd::byte 除外

【讨论】:

    猜你喜欢
    • 2019-06-18
    • 1970-01-01
    • 2013-12-13
    • 2013-07-24
    • 2021-07-20
    • 2018-01-09
    • 1970-01-01
    • 2018-05-26
    • 1970-01-01
    相关资源
    最近更新 更多