使用 [] 运算符在 unordered_map 中插入元素时出现分段错误
Segmentation fault when inserting elements in unordered_map using the [] operator
正如标题所说,unordered_map使用[]运算符插入元素时,会出现Segmentation fault,而我最困惑的地方是在使用resize( )在vec上,而我在使用push_back()时程序没有问题。我不明白是什么原因造成的。
#include<iostream>
#include<unordered_map>
#include<vector>
#include<cstdlib>
#include<ctime>
using namespace std;
struct Element
{
int key;
vector<int> vec;
int flag;
};
class Test
{
private:
unordered_map<int,Element *> map;
public:
Element *getElement(int key,int flag)
{
Element *element;
auto temp = map.find(key);
if(temp==map.end()||flag == temp->second->flag)
{
element = new Element();
element->key = key;
element->flag = flag;
if(temp != map.end())
{
delete temp->second;
map.erase(key);
}
map[key] = element;
}
else
{
element = map[key];
}
return element;
}
};
int main()
{
srand((unsigned)time(nullptr));
Test test;
for (size_t i = 0; i < 100000; i++)
{
/* code */
int vecSize = rand()%100;
int key = rand()%5000;
int flag = rand()%5000;
Element *element = test.getElement(key,flag);
if(element->vec.size()==0)
{
element->vec.resize(vecSize,0);
}
for (size_t i = 0; i < vecSize; i++)
{
element->vec[i] = rand()%10000;
}
}
return 0;
}
输出:
Program received signal SIGSEGV, Segmentation fault.
0x000055555555716e in std::__detail::_Hash_node<std::pair<int const, Element*>, false>::_M_next (this=0x8470000046a) at /usr/include/c++/7/bits/hashtable_policy.h:298
298 { return static_cast<_Hash_node*>(this->_M_nxt); }
(gdb) bt
#0 0x000055555555716e in std::__detail::_Hash_node<std::pair<int const, Element*>, false>::_M_next (this=0x8470000046a) at /usr/include/c++/7/bits/hashtable_policy.h:298
#1 0x000055555555782c in std::_Hashtable<int, std::pair<int const, Element*>, std::allocator<std::pair<int const, Element*> >, std::__detail::_Select1st, std::equal_to<int>, std::hash<int>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<false, false, true> >::_M_rehash_aux (this=0x7fffffffe370, __n=337) at /usr/include/c++/7/bits/hashtable.h:2098
#2 0x0000555555556ef2 in std::_Hashtable<int, std::pair<int const, Element*>, std::allocator<std::pair<int const, Element*> >, std::__detail::_Select1st, std::equal_to<int>, std::hash<int>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<false, false, true> >::_M_rehash
(this=0x7fffffffe370, __n=337, __state=@0x7fffffffe220: 167) at /usr/include/c++/7/bits/hashtable.h:2071
#3 0x00005555555564e0 in std::_Hashtable<int, std::pair<int const, Element*>, std::allocator<std::pair<int const, Element*> >, std::__detail::_Select1st, std::equal_to<int>, std::hash<int>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<false, false, true> >::_M_insert_unique_node (this=0x7fffffffe370, __bkt=88, __code=1424, __node=0x55555577a330) at /usr/include/c++/7/bits/hashtable.h:1718
#4 0x0000555555555992 in std::__detail::_Map_base<int, std::pair<int const, Element*>, std::allocator<std::pair<int const, Element*> >, std::__detail::_Select1st, std::equal_to<int>, std::hash<int>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<false, false, true>, true>::operator[] (this=0x7fffffffe370, __k=@0x7fffffffe2f4: 1424) at /usr/include/c++/7/bits/hashtable_policy.h:728
#5 0x00005555555554db in std::unordered_map<int, Element*, std::hash<int>, std::equal_to<int>, std::allocator<std::pair<int const, Element*> > >::operator[] (this=0x7fffffffe370,
__k=@0x7fffffffe2f4: 1424) at /usr/include/c++/7/bits/unordered_map.h:973
#6 0x00005555555551ca in Test::getElement (this=0x7fffffffe370, key=1424, flag=318) at main.cpp:35
#7 0x0000555555554e23 in main () at main.cpp:56
让我们来看看您的主要设计决策:
unordered_map<int,Element *> map;
您正在使用“裸指针”,它应该保留用于数据结构(即您的 map
)需要引用某些东西但它不拥有它的情况。在您的程序中情况并非如此:没有其他人拥有 Element
个对象。所以你应该明确地存储它们,并且 return 引用:
unordered_map<int,Element> map;
Element& getElement(int key,int flag);
正如其他人也指出的那样:您的程序可以更简单、更正确。如果你没有编写正确的 C++,你就会让自己的生活变得太难了。
编辑,因为您表示您受困于遗留问题 API:
仍然可以保留 API 但重做实现。如果 API 要求您 return 指向内部的 *
指针(而不是我建议的引用),则将元素存储在内部作为智能指针,并且 return get()
结果。
正如标题所说,unordered_map使用[]运算符插入元素时,会出现Segmentation fault,而我最困惑的地方是在使用resize( )在vec上,而我在使用push_back()时程序没有问题。我不明白是什么原因造成的。
#include<iostream>
#include<unordered_map>
#include<vector>
#include<cstdlib>
#include<ctime>
using namespace std;
struct Element
{
int key;
vector<int> vec;
int flag;
};
class Test
{
private:
unordered_map<int,Element *> map;
public:
Element *getElement(int key,int flag)
{
Element *element;
auto temp = map.find(key);
if(temp==map.end()||flag == temp->second->flag)
{
element = new Element();
element->key = key;
element->flag = flag;
if(temp != map.end())
{
delete temp->second;
map.erase(key);
}
map[key] = element;
}
else
{
element = map[key];
}
return element;
}
};
int main()
{
srand((unsigned)time(nullptr));
Test test;
for (size_t i = 0; i < 100000; i++)
{
/* code */
int vecSize = rand()%100;
int key = rand()%5000;
int flag = rand()%5000;
Element *element = test.getElement(key,flag);
if(element->vec.size()==0)
{
element->vec.resize(vecSize,0);
}
for (size_t i = 0; i < vecSize; i++)
{
element->vec[i] = rand()%10000;
}
}
return 0;
}
输出:
Program received signal SIGSEGV, Segmentation fault.
0x000055555555716e in std::__detail::_Hash_node<std::pair<int const, Element*>, false>::_M_next (this=0x8470000046a) at /usr/include/c++/7/bits/hashtable_policy.h:298
298 { return static_cast<_Hash_node*>(this->_M_nxt); }
(gdb) bt
#0 0x000055555555716e in std::__detail::_Hash_node<std::pair<int const, Element*>, false>::_M_next (this=0x8470000046a) at /usr/include/c++/7/bits/hashtable_policy.h:298
#1 0x000055555555782c in std::_Hashtable<int, std::pair<int const, Element*>, std::allocator<std::pair<int const, Element*> >, std::__detail::_Select1st, std::equal_to<int>, std::hash<int>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<false, false, true> >::_M_rehash_aux (this=0x7fffffffe370, __n=337) at /usr/include/c++/7/bits/hashtable.h:2098
#2 0x0000555555556ef2 in std::_Hashtable<int, std::pair<int const, Element*>, std::allocator<std::pair<int const, Element*> >, std::__detail::_Select1st, std::equal_to<int>, std::hash<int>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<false, false, true> >::_M_rehash
(this=0x7fffffffe370, __n=337, __state=@0x7fffffffe220: 167) at /usr/include/c++/7/bits/hashtable.h:2071
#3 0x00005555555564e0 in std::_Hashtable<int, std::pair<int const, Element*>, std::allocator<std::pair<int const, Element*> >, std::__detail::_Select1st, std::equal_to<int>, std::hash<int>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<false, false, true> >::_M_insert_unique_node (this=0x7fffffffe370, __bkt=88, __code=1424, __node=0x55555577a330) at /usr/include/c++/7/bits/hashtable.h:1718
#4 0x0000555555555992 in std::__detail::_Map_base<int, std::pair<int const, Element*>, std::allocator<std::pair<int const, Element*> >, std::__detail::_Select1st, std::equal_to<int>, std::hash<int>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<false, false, true>, true>::operator[] (this=0x7fffffffe370, __k=@0x7fffffffe2f4: 1424) at /usr/include/c++/7/bits/hashtable_policy.h:728
#5 0x00005555555554db in std::unordered_map<int, Element*, std::hash<int>, std::equal_to<int>, std::allocator<std::pair<int const, Element*> > >::operator[] (this=0x7fffffffe370,
__k=@0x7fffffffe2f4: 1424) at /usr/include/c++/7/bits/unordered_map.h:973
#6 0x00005555555551ca in Test::getElement (this=0x7fffffffe370, key=1424, flag=318) at main.cpp:35
#7 0x0000555555554e23 in main () at main.cpp:56
让我们来看看您的主要设计决策:
unordered_map<int,Element *> map;
您正在使用“裸指针”,它应该保留用于数据结构(即您的 map
)需要引用某些东西但它不拥有它的情况。在您的程序中情况并非如此:没有其他人拥有 Element
个对象。所以你应该明确地存储它们,并且 return 引用:
unordered_map<int,Element> map;
Element& getElement(int key,int flag);
正如其他人也指出的那样:您的程序可以更简单、更正确。如果你没有编写正确的 C++,你就会让自己的生活变得太难了。
编辑,因为您表示您受困于遗留问题 API:
仍然可以保留 API 但重做实现。如果 API 要求您 return 指向内部的 *
指针(而不是我建议的引用),则将元素存储在内部作为智能指针,并且 return get()
结果。