2013-02-02 9 views
5

Śledziłem błąd związany z użyciem __m128 (wektor SSE) jako wartości w std :: unordered_map. Powoduje to błąd segmentacji środowiska wykonawczego przy użyciu komendy mingw32 g ++ 4.7.2.STL unordered_map zawiesza się z wartościami __m128

Proszę zobaczyć przykład poniżej. Czy jest jakiś powód, dla którego to powinno zawieść? A może może istnieć obejście tego problemu? (Próbowałem owijać wartość w klasie, ale to nie pomogło.) Dzięki.

#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; 
} 

ustawienia kompilacji: g ++ -march = rodzimy -std = C++ 11

+1

Niektóre pokrewne czytanie tutaj: http://stackoverflow.com/questions/4424741/aligned-types-and-passing-arguments-by-value – Joe

+0

kiedy dereference wskaźnik do typu '__m128', wynikowe funkcje ładowania/składowania, które emituje kompilator, są zazwyczaj zrównane z odmianą, więc przyjmuje on nieodłączne założenie, że pamięć podstawowa jest dopasowywany w zależności od potrzeb (typ 16-bajtowy w tym przypadku). Zgaduję, że gdzieś w kodzie kontenera, wskaźnik do "__m128" jest dereferenced i założenia wyrównania nie trzyma, co powoduje błąd segmentacji. Jeśli uruchomisz program z debuggerem i sprawdzisz wartość wskaźnika po awarii, powinieneś być w stanie to zobaczyć. –

+0

Czy w ogóle nie ma dostępu do niezdefiniowanego zachowania 'm [0]'? – hirschhornsalz

Odpowiedz

2

C++ aktualnie nie obsługuje alokacji dynamicznej typów wyrównanych. W przypadku zwykłych ABI w standardzie x86 standardowe wyrównanie wynosi 8, a __m128 ma wyrównanie 16 bajtów, więc jest on zbyt duży. W przypadku zwykłych ABI x86_64 standardowe wyrównanie wynosi 16, co sprawia, że ​​__m128 jest bezpieczne (ale __m256 jest znowu niebezpieczne z 32-bajtowym wyrównaniem).

Zobacz ten papier do ewentualnej zmiany w kolejnym standardem, która stałaby rzeczy „po prostu działa”: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3396.htm

W międzyczasie, można podać własną przydzielania, na przykład na podstawie aligned_alloc (C11), posix_memalign (UNIX), _aligned_malloc (Microsoft), itp

3

Są 2 problemy dotyczące Wyrównanie:

Czy ABI zapewnienia __m128 zmienne są zawsze ustawione na stos?

Czy operator globalny new zwraca pamięć wyrównaną do typu __m128? to znaczy zwraca pamięć z 16-bajtowym wyrównaniem.

+2

Dzięki za opinie; to zdecydowanie problem wyrównania. Wygląda na to, że kontenery STL powinny być zaprojektowane tak, aby respektować właściwości wyrównania elementów. Prawdopodobnie na razie wymaga to niestandardowego przydziału pamięci? – Hugues