C++ gcc中的SEGV';s std::无序_图
我在gcc 4.7.2的C++ gcc中的SEGV';s std::无序_图,c++,gcc,c++11,unordered-map,C++,Gcc,C++11,Unordered Map,我在gcc 4.7.2的unordered_map 在find()中,它调用\u mu find\u node,该节点依次调用\u mu find\u before\u node,传入桶号、我们正在搜索的键和散列码 在\u M\u find\u before\u node中,它查找相关bucket中的第一个节点: _BaseNode* __prev_p = _M_buckets[__n]; 然后获取以下节点: _Node* __p = static_cast<_Node*>(__p
unordered_map
在find()
中,它调用\u mu find\u node
,该节点依次调用\u mu find\u before\u node
,传入桶号、我们正在搜索的键和散列码
在\u M\u find\u before\u node
中,它查找相关bucket中的第一个节点:
_BaseNode* __prev_p = _M_buckets[__n];
然后获取以下节点:
_Node* __p = static_cast<_Node*>(__prev_p->_M_nxt);
除非您在gcc
std::unorderd_map
实现中检测到错误,否则最有可能的错误原因是您执行了以下操作:
std::unorderd_map<MyKey, MyValue> my_map;
auto it = my_map.find(some_key); // if some_key was not found, it == my_map.end()
do something with *it; // kaboom! derefence of past-the-end iterator
我不是100%了解无序映射的内部工作原理-是要求bucket的\u nxt
中的第一个节点非空,还是这是一个bug
这个问题显然是针对GCC的实现的,但我非常确定,如果\u m_bucket[\uu n]
是非空的,那么\u m_bucket[\uu n]->\u m_nxt
也应该是非空的
i、 e.如果bucket为空,则\u M_bucket[\u n]==nullptr
,如果bucket为非空,则\u M_bucket[\u n]->\u M_nxt
是bucket中的第一个节点
试着用
-D_GLIBCXX_DEBUG
构建,看看它是否识别出代码中的问题,可能存在错误,但更有可能是您以某种方式损坏了容器或使用了错误的容器。这个问题现在已经很老了,但我最近也遇到了同样的问题,下面是如何重现它的示例代码
#include <chrono>
#include <iostream>
#include <thread>
#include <unordered_map>
int main()
{
std::unordered_map< std::string, int > m_Map{};
m_Map.insert(std::make_pair("a", 0x61));
auto count{1000u};
auto t_remove = std::thread([&m_Map, &count]() {
while (1)
{
m_Map.erase("a");
std::this_thread::sleep_for(std::chrono::nanoseconds(count));
if(count > 10)
{
count-=10;
}
else
{
count = 1000u;
}
m_Map.insert(std::make_pair("a", 0x61));
}
});
while (1)
{
auto it = m_Map.find("a");
if (it != m_Map.end())
{
std::cerr << "Map has a " << it->first << " = " << it->second << "\n";
}
else
{
std::cerr << "Map does not have a \"a\"\n";
}
}
t_remove.join();
return 0;
}
#包括
#包括
#包括
#包括
int main()
{
无序映射m\u映射{};
m_Map.insert(std::make_pair(“a”,0x61));
自动计数{1000u};
自动t_remove=std::thread([&m_映射,&count](){
而(1)
{
m_地图删除(“a”);
std::this_线程::sleep_for(std::chrono::纳秒(计数));
如果(计数>10)
{
计数-=10;
}
其他的
{
计数=1000u;
}
m_Map.insert(std::make_pair(“a”,0x61));
}
});
而(1)
{
自动it=m_Map.find(“a”);
if(it!=m_Map.end())
{
std::cerr为什么不显示触发此错误的代码?如果代码正确,您应该提交错误报告。如果不正确,您的问题就会得到解决:)就个人而言,我会首先在我自己的代码中查找错误。您有自己的代码片段复制此错误吗?不能在简单的示例中重新编写-我正在尝试!:/这是我的错误ry整洁,确实应该被标记为正确答案。@HubertLiberacki整洁程度如何?因为两个线程处于数据竞争中。应该有同步访问共享映射。此代码只是一个明显的错误,任何事情都可能发生。
if (it != my_map.end()) {
do something with *it;
}
#include <chrono>
#include <iostream>
#include <thread>
#include <unordered_map>
int main()
{
std::unordered_map< std::string, int > m_Map{};
m_Map.insert(std::make_pair("a", 0x61));
auto count{1000u};
auto t_remove = std::thread([&m_Map, &count]() {
while (1)
{
m_Map.erase("a");
std::this_thread::sleep_for(std::chrono::nanoseconds(count));
if(count > 10)
{
count-=10;
}
else
{
count = 1000u;
}
m_Map.insert(std::make_pair("a", 0x61));
}
});
while (1)
{
auto it = m_Map.find("a");
if (it != m_Map.end())
{
std::cerr << "Map has a " << it->first << " = " << it->second << "\n";
}
else
{
std::cerr << "Map does not have a \"a\"\n";
}
}
t_remove.join();
return 0;
}
Thread 1 "find_stress_tes" received signal SIGSEGV, Segmentation fault.
0x000000000040505b in std::__detail::_Equal_helper<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, int>, std::__detail::_Select1st, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, unsigned long, true>::_S_equals (__eq=..., __extract=..., __k="a", __c=4993892634952068459, __n=0x0)
at /usr/include/c++/5/bits/hashtable_policy.h:1322
1322 { return __c == __n->_M_hash_code && __eq(__k, __extract(__n->_M_v())); }
(gdb) bt
#0 0x000000000040505b in std::__detail::_Equal_helper<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, int>, std::__detail::_Select1st, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, unsigned long, true>::_S_equals (__eq=..., __extract=..., __k="a", __c=4993892634952068459, __n=0x0)
at /usr/include/c++/5/bits/hashtable_policy.h:1322
#1 0x0000000000404b2a in std::__detail::_Hashtable_base<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, int>, std::__detail::_Select1st, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Hashtable_traits<true, false, true> >::_M_equals (this=0x7fffffffdd40, __k="a",
__c=4993892634952068459, __n=0x0) at /usr/include/c++/5/bits/hashtable_policy.h:1704
#2 0x00000000004044ef in std::_Hashtable<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, int>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, int> >, std::__detail::_Select1st, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<true, false, true> >::_M_find_before_node (this=0x7fffffffdd40, __n=1,
__k="a", __code=4993892634952068459) at /usr/include/c++/5/bits/hashtable.h:1433
#3 0x0000000000403e50 in std::_Hashtable<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, int>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, int> >, std::__detail::_Select1st, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<true, false, true> >::_M_find_node (this=0x7fffffffdd40, __bkt=1, __key="a",
__c=4993892634952068459) at /usr/include/c++/5/bits/hashtable.h:632
#4 0x000000000040392b in std::_Hashtable<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, int>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, int> >, std::__detail::_Select1st, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<true, false, true> >::find (this=0x7fffffffdd40, __k="a")
at /usr/include/c++/5/bits/hashtable.h:1307
#5 0x0000000000403675 in std::unordered_map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, int> > >::find (this=0x7fffffffdd40,
__x="a") at /usr/include/c++/5/bits/unordered_map.h:615
#6 0x000000000040184b in main () at ../find_stress_test/main.cpp:40