【发布时间】:2012-11-27 09:16:25
【问题描述】:
我有一个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
编辑:我不认为它实际上会有所不同在哪里只要我给它相同的参数,我就调用该函数,但显然它确实:
std::for_each(blocks.begin(), blocks.end(), [&](const Block& block) {
map.at(block);
}
导致错误,而只是:
const Block& block = blocks[0];
map.at(block);
工作得很好(blocks 是一个简单的vector<Block>&)
【问题讨论】:
-
与你的问题无关,但你不应该把函数/类/等。在
std命名空间中。 -
@Joachim 不知道 g 何时将自己偷运到那里 ;) 还添加了 gdb 回溯。关于
std命名空间:据我所知,如果我不想在每次用我的结构声明一个映射时都指定哈希函数,那就是要走的路——如果有更好的方法,我显然会全神贯注,但是因为我只是专门研究一个不应该那么糟糕的现有结构吗? -
@juanchopanza 是的,我知道,问题似乎不是哈希函数本身,而是映射的内部变量
den显然不应该是 0 的事实。 -
@JoachimPileborg,你的第一条评论是什么意思?专门化 std::hash 必须 在 std:: 中完成,这是完全合法的。你的建议很好,但专业化是个例外。 (另一个常见的例子是专门化 std::less)