14

unordered_map<Block, int>次のように定義された単純な構造体であるwith Block があります。

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

マップにアクセスしようとすると、gdb で次のエラー メッセージが表示されます (g++ 4.7.1 と clang++ 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; }

私の libstdc++ バージョンは 3.4.17 (つまり、GCC 4.7 のバージョン) です。

関連するバックトレース:

#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

編集:同じ引数を指定する限り、実際に関数を呼び出す場所に違いがあるとは思いませんでしたが、明らかにそうです:

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

ただ持っている間、エラーにつながります:

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

完全に正常に動作します(blocks単純ですvector<Block>&

4

5 に答える 5

14

余談: ハッシュ関数が例外をスローできない場合は、例外仕様を指定することが非常に重要noexceptです。そうでない場合、ハッシュ テーブルは要素自体と一緒にすべての要素のハッシュ コードを格納する必要があります (メモリ使用量が増加し、パフォーマンスに影響します)。 not throw はハッシュ コードを再計算する必要はありません。

SIGFPE はゼロによる除算を意味し、バックトレースからは次のようになります。

    { return __num % __den; }

これはおそらく__denゼロを意味します。その値はハッシュ マップのバケット カウントから取得されます。これはゼロであってはなりません。

m._M_bucket_countクラッシュするときがゼロであることを確認できますか?

もしそうなら、それはあなたが何らかの形でマップを破損したことを示しているか ( -D_GLIBCXX_DEBUGlibstdc++ デバッグ モード チェックを有効にするために でコンパイルしようとしましたか? で実行しようとしましたvalgrindか?)、または libstdc++ コードにバグがあります (これは可能ですが、可能性は低いです) )。

以下の他の回答のいくつかは、マップがどのように破損する可能性があるかの例を示していmallocますmemset.

もう 1 つの可能性は、ハッシュ マップがグローバル変数であり、別のグローバル変数のコンストラクターからアクセスしていて、静的初期化順序の大失敗が発生している可能性です。コンストラクターが実行される前にマップが使用される場合、バケット数はゼロになります。

于 2013-01-10T17:42:45.610 に答える
8

私の場合、静的初期化の大失敗が原因で同じ問題が発生しました。1 つのオブジェクト ファイルから、2 番目のオブジェクト ファイルで定義された static std::unordered_map に対して emplace() を呼び出しました。開始時のデータが BSS にあったため、バケット カウントの値は 0 => SIGFPE でした。

于 2016-04-04T15:27:30.330 に答える
4

私はまったく同じ問題を抱えていました。これは memset がコンテナー データに誤って適用されたことが原因でした。

于 2014-10-19T06:31:58.530 に答える