我有unordered_map<Block, int>
,其中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
编辑:我认为它实际上没有什么区别 where 我调用该函数只要我给它相同的参数,但显然它确实:
std::for_each(blocks.begin(), blocks.end(), [&](const Block& block) {
map.at(block);
}
导致错误,而只是:
const Block& block = blocks[0];
map.at(block);
完全正常(blocks
是一个简单的vector<Block>&
)
答案 0 :(得分:8)
除此之外:如果你的哈希函数不能抛出,那么给它一个noexcept
异常规范是非常重要的,否则哈希表需要将每个元素的哈希码与元素本身一起存储(这会增加内存使用并影响性能)以便不必抛出的容器操作不必重新计算哈希码。
SIGFPE意味着除以零,并且它从回溯中发生:
{ return __num % __den; }
这可能意味着__den
为零。该值来自哈希映射的桶计数,该计数不应为零。
您能确认崩溃时m._M_bucket_count
是否为零?
如果是这样,那么表明你已经以某种方式破坏了地图(你是否尝试使用-D_GLIBCXX_DEBUG
进行编译以打开libstdc ++调试模式检查?你试过在valgrind
下运行吗?)或者那里libstdc ++代码中的一个错误。
答案 1 :(得分:4)
我有完全相同的问题。它是由memset意外应用于容器数据引起的。
答案 2 :(得分:3)
在我的情况下,由于静态init惨败导致同样的问题。 我从一个目标文件中调用了emplace方法,用于在第二个目标文件中定义的静态std :: unordered_map。由于起始数据是在BSS,因此桶数的值为零=&gt; SIGFPE。
答案 3 :(得分:1)
还将以STL代码发布有关FPE的情况。
代码使用malloc()分配std :: unordered_map。当然,这不会调用构造函数,从而导致异常状态。
答案 4 :(得分:0)
遵循其他用户在STL代码中报告导致FPE的自身情况的传统,这里是我的:
自从我们升级了编译器以来,我们在std :: map中就拥有了非常完美的代码,并且开始死于SIGFPE。事实证明,我在c ++ 11模式下使用gcc 4.8.5编译了gcc 9.2 ,这不是正常的事情-正常的gcc编译始终在gnu ++ 98模式下进行。 / p>
这导致4.8.5 gcc(其对c ++ 11的支持不完全/非官方)产生了错误的9.2 gcc,这偶尔会生成二进制文件,这些二进制文件将显示各种不相关的故障。例如,尝试调试以上SIGFPE会导致在使用-D_GLIBCXX_DEBUG
编译时std :: basic_string析构函数中出现SIGSEGV,而使用-fsanitize=address
检测到无关的内存损坏。
课程有两个方面: