访问unordered_map时的SIGFPE

Voo*_*Voo 10 c++ gcc clang libstdc++

我有一个unordered_map<Block, int>块是一个简单的结构定义如下:

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;
    }
};
} 
Run Code Online (Sandbox Code Playgroud)

当试图访问地图时,我确实在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; }
Run Code Online (Sandbox Code Playgroud)

我的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
Run Code Online (Sandbox Code Playgroud)

编辑:我没想到它居然会有所作为的地方,只要我给它相同的参数我打电话的功能,但显然它的作用:

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

导致错误,而只是:

const Block& block = blocks[0];
map.at(block);
Run Code Online (Sandbox Code Playgroud)

完美无缺(blocks简单vector<Block>&)

Jon*_*ely 9

另外:如果你的哈希函数不能抛出,那么给它一个noexcept异常规范是非常重要的,否则哈希表需要将每个元素的哈希代码与元素本身一起存储(这会增加内存使用并影响性能),以便必须进行容器操作不抛不必重新计算哈希码.

SIGFPE意味着除以零,从这里发生的回溯:

    { return __num % __den; }
Run Code Online (Sandbox Code Playgroud)

这可能意味着__den零.该值来自哈希映射的桶计数,该计数不应为零.

你可以确认崩溃时m._M_bucket_count是零吗?

如果是这样,那么表明你已经以某种方式破坏了地图(你是否尝试过编译-D_GLIBCXX_DEBUG以打开libstdc ++调试模式检查?你试过运行valgrind吗?)或者libstdc ++代码中有一个错误.

  • 阅读最后一段。调试您的程序以了解损坏是如何发生的。 (2认同)

use*_*854 8

在我的情况下,由于静态初始化失败而发生了同样的问题。从一个目标文件中,我为第二个目标文件中定义的静态 std::unordered_map 调用了 emplace()。由于开始时数据在 BSS,桶计数的值为零 => SIGFPE。