【问题标题】:STL unordered_map crashes with __m128 valuesSTL unordered_map 因 __m128 值而崩溃
【发布时间】:2013-01-17 20:40:04
【问题描述】:

我跟踪了一个使用 __m128(SSE 向量)作为 std::unordered_map 中的值的错误。 这会导致 mingw32 g++4.7.2 出现运行时分段错误。

请看下面的例子。 有什么理由会失败吗? 或者,是否有解决方法? (我尝试将值包装在一个类中,但没有帮助。) 谢谢。

#include <unordered_map>
#include <xmmintrin.h>          // __m128
#include <iostream>

int main()
{
    std::unordered_map<int,__m128> m;
    std::cerr << "still ok\n";
    m[0] = __m128();
    std::cerr << "crash in previous statement\n";
    return 0;
}

编译设置: g++ -march=native -std=c++11

【问题讨论】:

  • 一些相关阅读在这里:stackoverflow.com/questions/4424741/…
  • 当您取消引用指向 __m128 类型的指针时,编译器发出的结果加载/存储函数通常是对齐的种类,因此它假设底层内存对齐为类型需要(在这种情况下为 16 字节对齐)。我猜在容器代码的某个地方,指向__m128 的指针被取消引用,并且对齐假设不成立,从而导致分段错误。如果您使用调试器运行程序并在崩溃后检查指针值,您应该能够看到这一点。
  • 无论如何都不能访问m[0] 未定义的行为吗?
  • 我希望对m[0] 的访问不是特别的;我在整个代码中都使用它;您是否有任何建议 key==0 被保留?

标签: stl sse unordered-map


【解决方案1】:

关于对齐有两个问题:

ABI 是否确保 __m128 变量始终在堆栈上对齐?

全局new 运算符是否返回与__m128 类型适当对齐的内存?即,返回 16 字节对齐的内存。

【讨论】:

  • 感谢您的反馈;这绝对是对齐问题。似乎 STL 容器的设计应该尊重元素的对齐属性。可能现在这需要自定义内存分配器?
【解决方案2】:

C++ 目前不处理过度对齐类型的动态分配。对于通常的 x86 ABI,标准对齐方式为 8,而 __m128 的对齐方式为 16 字节,因此过度对齐。对于通常的 x86_64 ABI,标准对齐是 16,这使得 __m128 是安全的(但 __m256 又是不安全的,因为它的 32 字节对齐)。

请参阅本文,了解下一个标准的可能更改,以使事情“正常工作”: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3396.htm

同时,您可以指定自己的分配器,例如基于aligned_alloc (C11)、posix_memalign (unix)、_aligned_malloc (Microsoft) 等。

【讨论】:

    猜你喜欢
    • 2011-03-13
    • 2013-03-09
    • 2015-12-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多