【问题标题】:How to check if a pointer points to a properly aligned memory location?如何检查指针是否指向正确对齐的内存位置?
【发布时间】:2017-06-24 21:42:24
【问题描述】:

给定某个存储的void *,如何检查它是否指向正确对齐的存储而没有任何实现定义的行为?

我们当然有std::align,但是有没有更有效的方法来做到这一点?

template <std::size_t alignment>
inline bool is_aligned(void * ptr) noexcept {
    std::size_t max = 1u;
    return std::align(alignment, 1u, ptr, max);
}

PS:我需要以与 C++ 标准兼容的方式执行此操作,而不依赖于任何特定于平台(实现定义)的 hack。

PPS:我为我的(理解)英语道歉,它不是我的母语。


编辑(2018.08.24):从标题中删除了“有效”,添加了更多措辞以强调我不希望任何定义的实现或特定于平台的行为。

【问题讨论】:

  • 另请注意,对齐是根据定义平台特定的,并且对从 reinterpret_cast 返回的数值进行操作,例如 @Some 建议的本质上是未定义或实现定义的行为。
  • 最后,如果您使用newnew[] 分配了内存,您可以确定内存应该与您正在使用的类型完全对齐。也许您可以通过检查对齐方式来启发我们了解您实际尝试解决的问题?为什么需要检查?
  • @Someprogrammerdude 当有一个包含任意原始数据的缓冲区,并且需要检查它的一部分是否可以作为某种类型直接访问 T 或者是否需要使用 @Someprogrammerdude 时,这可能很有用987654328@ 在以T 类型访问这些数据之前/之后将相应的数据从缓冲区复制到缓冲区。
  • @Someprogrammerdude 在 C++17 之前仅适用于具有标准对齐的类型,不适用于 struct OveralignedInt { alignas(1024) int i; };
  • @jotik 即使满足对齐要求,也可以将任意原始数据(char 缓冲区)作为T 访问。您必须首先以放置new 开始对象的生命周期。

标签: c++ c++11 c++14 memory-alignment c++17


【解决方案1】:

如果在按所需对齐方式除以地址时余数不为零,则地址未对齐。

inline bool
is_aligned(const void * ptr, std::uintptr_t alignment) noexcept {
    auto iptr = reinterpret_cast<std::uintptr_t>(ptr);
    return !(iptr % alignment);
}

由于演员阵容,这不能是 constexpr。

此外,这依赖于实现定义的事实,即从指针到整数的转换必须保留地址的数字表示。正如 cmets 所指出的,标准并不能保证这一点,因此该功能不一定可移植到所有平台。这也是正确的,因为实现提供std::uintptr_t 是可选的。


我希望只有在对齐类型时才需要它,所以这可能更方便:

template<class T>
bool
is_aligned(const void * ptr) noexcept {
    auto iptr = reinterpret_cast<std::uintptr_t>(ptr);
    return !(iptr % alignof(T));
}

【讨论】:

  • 任何指针都可以转换为无符号整数,其大小至少为uintptr_t。但是,结果是实现定义的。您假设使用了一个通用的实现,并且内存模型基本上是平坦的,这在当今很有可能,但不能保证。
  • @ArneVogel 是的,似乎这不能保证严格地移植到晦涩的平台,在这些平台上,转换可能会改变对齐方式。
  • @PhilArmstrong 2 的补码不用于无符号数,它没有相关性:) 但是,任何体面的优化器都可以进行这种转换。
  • @PhilArmstrong 我测试了你的函数,还测试了将 constexpr 添加到我的模板中。令我惊讶的是,它起作用了。我很困惑,因为我不明白为什么 reinterpret_cast 可以在 constexpr 模板中使用,但不能在常规 constexpr 函数中使用。你能解释/参考标准吗?
  • @PhilArmstrong :没有模板参数将满足所有 constexpr 要求的 Constexpr 函数模板格式不正确,不需要诊断。这就是你和@user2079303 都遇到的问题。
猜你喜欢
  • 2015-07-13
  • 1970-01-01
  • 2012-10-26
  • 2011-03-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-20
  • 2011-06-07
相关资源
最近更新 更多