2012-11-27 10 views
8

Mam unordered_map<Block, int> z bloku jest proste struct zdefiniowane następująco:SIGFPE przy dostępie unordered_map

struct Block { 
    size_t start; 
    size_t end; 

    bool operator==(const Block& b) const { 
     return start == b.start && end == b.end; 
    } 
}; 

namespace std { 
template<> 
struct hash<Block> { 
    size_t operator()(const Block& b) const { 
     return b.start; 
    } 
}; 
} 

Gdy próbuje uzyskać dostęp do mapy, robię się następujący komunikat o błędzie w gdb (taki sam dla obu g ++ 4.7 0,1 jak również brzękiem ++ 3.1):

Program received signal SIGFPE, Arithmetic exception. 
0x0000000000401e0b in std::__detail::_Mod_range_hashing::operator() (this=0x7fffffffd8e0, __num=0, __den=0) 
    at /usr/include/c++/4.7/bits/hashtable_policy.h:245 
245  { return __num % __den; } 

Moja libstdC++ wersja 03/04/17 (czyli wersja z GCC 4.7)

Stosowna backtrace:

#0 0x0000000000401e0b in std::__detail::_Mod_range_hashing::operator() (this=0x7fffffffd8e0, __num=0, __den=0) 
    at /usr/include/c++/4.7/bits/hashtable_policy.h:245 
#1 0x0000000000407199 in std::__detail::_Hash_code_base<Block, std::pair<Block const, int>, std::_Select1st<std::pair<Block const, int> >, std::hash<Block>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, true>::_M_bucket_index (this=0x7fffffffd8e0, __c=0, __n=0) at /usr/include/c++/4.7/bits/hashtable_policy.h:787 
#2 0x0000000000405230 in std::_Hashtable<Block, std::pair<Block const, int>, std::allocator<std::pair<Block const, int> >, std::_Select1st<std::pair<Block const, int> >, std::equal_to<Block>, std::hash<Block>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, true, false, true>::_M_bucket_index 
    (this=0x7fffffffd8e0, __k=..., __c=0) at /usr/include/c++/4.7/bits/hashtable.h:466 
#3 0x00000000004038de in std::__detail::_Map_base<Block, std::pair<Block const, int>, std::_Select1st<std::pair<Block const, int> >, true, std::_Hashtable<Block, std::pair<Block const, int>, std::allocator<std::pair<Block const, int> >, std::_Select1st<std::pair<Block const, int> >, std::equal_to<Block>, std::hash<Block>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, true, false, true> >::at (
    this=0x7fffffffd8e0, __k=...) at /usr/include/c++/4.7/bits/hashtable_policy.h:474 
#4 0x0000000000403001 in SplicedAlignment::FindOptimalEndBlock() const::{lambda(Block const&)#1}::operator()(Block const&) const (__closure=0x7fffffffd990, block=...) at splicing.cpp:151 
#5 0x00000000004040b3 in std::for_each<__gnu_cxx::__normal_iterator<Block const*, std::vector<Block, std::allocator<Block> > >, SplicedAlignment::FindOptimalEndBlock() const::{lambda(Block const&)#1}>(__gnu_cxx::__normal_iterator<Block const*, std::vector<Block, std::allocator<Block> > >, SplicedAlignment::FindOptimalEndBlock() const::{lambda(Block const&)#1}, SplicedAlignment::FindOptimalEndBlock() const::{lambda(Block const&)#1}) (__first=..., __last=..., __f=...) 
    at /usr/include/c++/4.7/bits/stl_algo.h:4442 

Edit: Nie sądziłem, że to faktycznie zrobić różnicę gdzie I wywołać funkcję tak długo, jak dam mu te same argumenty, ale widocznie robi:

std::for_each(blocks.begin(), blocks.end(), [&](const Block& block) { 
    map.at(block); 
} 

przewody do błędu, a tylko o:

const Block& block = blocks[0]; 
map.at(block); 

prace perfekcyjnie (blocks jest prosty vector<Block>&)

+0

Niezwiązany z twoim problemem, ale nigdy nie powinieneś umieszczać funkcji/klas/etc. w przestrzeni nazw 'std'. –

+0

Oto możliwe zduplikowane http://stackoverflow.com/questions/8286103/strange-unordered-map-situation –

+0

@Sergey Widziałem to, ale rozwiązanie nie wydaje się mieć nic wspólnego z moim problemem - cały kod znajduje się w jednym pliku nagłówkowym (i tak głupio, żebym nie zauważył tego w oryginalnym pytaniu, mea culpa). – Voo

Odpowiedz

5

Na bok: jeśli twoja funkcja skrótu nie może rzucić, to jest bardzo ważne, aby nadać jej specyfikację wyjątku noexcept, w przeciwnym razie tablica asocjacyjna musi przechowywać kod skrótu każdego elementu obok samego elementu (co zwiększa użycie pamięci i wpływa na wydajność), więc operacje kontenera, które nie mogą rzucić, nie muszą ponownie obliczać kodu skrótu.

SIGFPE zakłada dzielenie przez zero i od backtrace zdarza się tutaj:

{ return __num % __den; } 

co prawdopodobnie oznacza __den wynosi zero. Ta wartość pochodzi z liczby bloków mapy mieszania, która nie powinna wynosić zero.

Czy możesz potwierdzić, że kiedy się zawiesza m._M_bucket_count ma wartość zero?

Jeśli tak, że albo wskazuje masz uszkodzony mapę jakoś (próbowałeś kompilacji z -D_GLIBCXX_DEBUG włączyć libstdC++ kontroli trybie debugowania? Czy próbowali uruchomiony pod valgrind?) Czy jest to błąd w libstdC++ kodu.

4

Miałem dokładnie ten sam problem. Zostało to spowodowane przez przypadkowo zastosowany memset do danych kontenera.

2

W moim przypadku ten sam problem wystąpił z powodu statycznego błędu początkowego. Z jednego pliku obiektowego nazwałem metodę emplace dla statycznego std :: unordered_map, która została zdefiniowana w drugim pliku obiektowym. Ponieważ na początku danych było na BSS, wartość liczby kubłów wynosiła zero => SIGFPE.

Powiązane problemy