2013-02-02 24 views
5

我跟蹤了使用__m128(SSE向量)作爲std :: unordered_map中的值的錯誤。 這會在mingw32 g ++ 4.7.2中導致運行時分段錯誤。STL unordered_map使用__m128值崩潰

請看下面的例子。 有沒有任何理由爲什麼這會失敗? 或者,可能有解決方法? (我嘗試在課堂中包裝價值,但它沒有幫助。) 謝謝。

#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 =本地-std = C++ 11

+1

一些相關閱讀這裏:http://stackoverflow.com/questions/4424741/aligned-types-and-passing-arguments-by-value – Joe

+0

當你解除引用指向「__m128」類型的指針,編譯器發出的結果加載/存儲函數通常是對齊的類型,因此它使內在的假設成爲底層內存根據需要對齊類型(在這種情況下爲16字節對齊)。我猜在容器代碼的某個地方,一個指向'__m128'的指針正在取消引用,並且對齊假設不成立,導致分段錯誤。如果您使用調試器運行程序並在崩潰後檢查指針值,則應該可以看到這一點。 –

+0

無論如何,沒有任何訪問'm [0]'未定義的行爲? – hirschhornsalz

回答

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(微軟)等

3

有關於對準2個問題:

是否ABI確保__m128變量總是在對齊疊加麼?

全球new操作符是否返回適合__m128類型的內存?即以16字節對齊的方式返回存儲器。

+2

感謝您的反饋意見;這絕對是一個對齊問題。看來STL容器應該被設計爲尊重元素的對齊屬性。可能現在這需要一個自定義內存分配器? – Hugues