【问题标题】:C++ alignment of class - member call on misaligned address类的 C++ 对齐 - 对未对齐地址的成员调用
【发布时间】:2019-04-28 07:58:10
【问题描述】:

我正在使用 UBSAN 并收到以下错误。请注意,我正在使用带有 -fsanitize=undefined 的 clang 6.0.1 进行编译。我已经阅读了一些关于 SO 的背景问题,但仍然无法解决我的特定问题。以下是供参考的背景问题:

以下是关于 C 类的一些注意事项:

  • C 类型的对象是使用new (C* o = new C();) 创建的
  • 类型 C 具有类型 A 的成员,该成员具有 64 字节对齐。我使用 alignof 验证了这一点。
  • C 是使用class alignas(64) C 声明的——但这并不能解决我的问题

我目前的假设是我需要使用 C++11 等效的 C++17 std::aligned_alloc 来使用对齐存储创建对象。但是,我不确定如何最好地做到这一点,或者它是否真的能解决我的问题。如果可能的话,我宁愿在 C 类的定义中解决一次问题,而不是每次创建 C 时。解决此问题以消除 UBSAN 错误的推荐方法是什么?

【问题讨论】:

  • 听起来你在正确的轨道上,扩展对齐通常是实现定义的,可能需要一些手握。甚至 C++17 的扩展对齐支持最终都是由实现定义的,您的实现可能会或可能不会为 64 调用 aligned_alloc。(C++17 中的新功能是您的实现可能现在调用 @ 987654328@.)

标签: c++ alignment


【解决方案1】:

如果您的类已经有一个需要 64 字节对齐的成员,那么该类也将不必要地使用 64 字节对齐。所以添加一个明确的alignas(64) 并不会真正改变任何事情。

这里的基本问题是分配函数(在 C++11 中)are only required 返回与fundamental alignment 对齐的内存。 C++11 让它实现定义了新的[expr.new]/1 是否支持过度对齐的类型。 C++17 introduced 新扩展对齐和用于处理该问题的附加分配函数(但是,是否支持以及哪些新扩展对齐仍然是实现定义的)。

如果您可以切换到支持 C++17 的编译器,那么您的代码很可能会正常工作。否则,您可能不得不使用一些特定于实现的函数来分配对齐的内存,或者只是推出您自己的解决方案,例如,基于std::align 和placement new(这也适用于C++11)......

【讨论】:

  • 谢谢。几个问题:1)我使用的是clang 6,所以我可以指定一个不同的标准-std=c++17。你是说不改变代码就可以工作吗?
  • 2) 我通常使用 posix_memalign 在 c++11 中创建对齐的动态分配内存。加上placement-new,会是推荐的c++11方法来解决这个问题吗?
  • @Kulluk007 我没有测试过,所以我不确定;但值得一试。如果它不起作用,如果非便携式解决方案足以满足您的需求,您可以使用posix_memalign。您可以重载此特定类型的 operator new/delete 函数以在后台使用posix_memalign,以便一切正常工作,并且您不必每次通过实例化这样的对象时手动编排正确的分配新的。这也应该允许unique_ptr 等像往常一样工作......
  • 谢谢。通过切换到 C++14 并使用 posix_memalign 和 placement-new,我能够消除 UBSAN 错误。由于我目前依赖的一些 macOS 库,我还无法升级到 C++17。但是,我现在从 ASAN 收到关于 malloc 和 delete 之间不匹配的可能无害的警告,因为我正在 malloc'ing 缓冲区,然后使用placement new,但在创建的对象上调用 delete。我没有在缓冲区上调用 free 因为 delete 也应该删除 malloced 缓冲区(对吗?)。我的理解是否正确,ASAN alloc-dealloc-mismatch 是无害的?
  • @Kulluk007 不,你的理解不正确。您不能使用delete 来释放使用malloc() 分配的内存。你必须使用free()
猜你喜欢
  • 1970-01-01
  • 2017-11-01
  • 2017-12-29
  • 2018-05-02
  • 2012-07-23
  • 1970-01-01
  • 2012-04-18
  • 1970-01-01
  • 2020-11-08
相关资源
最近更新 更多