当前位置: 首页 > 编程笔记 >

for循环中删除map中的元素valgrind检测提示error:Invalid read of size 8

樊宏义
2023-03-14
本文向大家介绍for循环中删除map中的元素valgrind检测提示error:Invalid read of size 8,包括了for循环中删除map中的元素valgrind检测提示error:Invalid read of size 8的使用技巧和注意事项,需要的朋友参考一下

废话不多说,先看下面一段代码

#include <iostream>
#include <map>
using namespace std;
class A
{
public:
typedef std::map<int, string> myMap;
void mapInsert(int i, string s)
{
map.insert(std::make_pair(i, s));
}
void deleteMap()
{
for (myMap::iterator it = map.begin(); it != map.end(); ++it)
{
map.erase(it->first);
}
}
private:
myMap map;
};
int main()
{
A a;
a.mapInsert(1, "1");
a.mapInsert(2, "2");
a.mapInsert(3, "3");
a.mapInsert(4, "4");
a.mapInsert(5, "5");
a.deleteMap();
return 0;
}

上述代码编译运行皆没有问题,但是用valgrind检测会提示错误:

valgrind --tool=memcheck --leak-check=full --track-origins=yes ./test # ~/test
==723953== Memcheck, a memory error detector
==723953== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al.
==723953== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info
==723953== Command: ./test
==723953== 
==723953== Invalid read of size 8
==723953== at 0x3431C69E60: std::_Rb_tree_increment(std::_Rb_tree_node_base*) (tree.cc:60)
==723953== by 0x40131C: std::_Rb_tree_iterator<std::pair<int const, std::string> >::operator++() (in /home/thm/test/test)
==723953== by 0x40117C: A::deleteMap() (in /home/thm/test/test)
==723953== by 0x400F4B: main (in /home/thm/test/test)
==723953== Address 0x4c580b8 is 24 bytes inside a block of size 48 free'd
==723953== at 0x4A06016: operator delete(void*) (vg_replace_malloc.c:480)
==723953== by 0x401E23: __gnu_cxx::new_allocator<std::_Rb_tree_node<std::pair<int const, std::string> > >::deallocate(std::_Rb_tree_node<std::pair<int const, std::string> >*, unsigned long) (in /home/thm/test/test)
==723953== by 0x401C99: std::_Rb_tree<int, std::pair<int const, std::string>, std::_Select1st<std::pair<int const, std::string> >, std::less<int>, std::allocator<std::pair<int const, std::string> > >::_M_put_node(std::_Rb_tree_node<std::pair<int const, std::string> >*) (in /home/thm/test/test)
==723953== by 0x401AA6: std::_Rb_tree<int, std::pair<int const, std::string>, std::_Select1st<std::pair<int const, std::string> >, std::less<int>, std::allocator<std::pair<int const, std::string> > >::_M_destroy_node(std::_Rb_tree_node<std::pair<int const, std::string> >*) (in /home/thm/test/test)
==723953== by 0x401729: std::_Rb_tree<int, std::pair<int const, std::string>, std::_Select1st<std::pair<int const, std::string> >, std::less<int>, std::allocator<std::pair<int const, std::string> > >::erase(std::_Rb_tree_iterator<std::pair<int const, std::string> >) (in /home/thm/test/test)
==723953== by 0x40134C: std::map<int, std::string, std::less<int>, std::allocator<std::pair<int const, std::string> > >::erase(std::_Rb_tree_iterator<std::pair<int const, std::string> >) (in /home/thm/test/test)
==723953== by 0x401170: A::deleteMap() (in /home/thm/test/test)
==723953== by 0x400F4B: main (in /home/thm/test/test)
==723953== 
==723953== Invalid read of size 8
==723953== at 0x3431C69E80: std::_Rb_tree_increment(std::_Rb_tree_node_base*) (tree.cc:68)
==723953== by 0x40131C: std::_Rb_tree_iterator<std::pair<int const, std::string> >::operator++() (in /home/thm/test/test)
==723953== by 0x40117C: A::deleteMap() (in /home/thm/test/test)
==723953== by 0x400F4B: main (in /home/thm/test/test)
==723953== Address 0x4c580a8 is 8 bytes inside a block of size 48 free'd
==723953== at 0x4A06016: operator delete(void*) (vg_replace_malloc.c:480)
==723953== by 0x401E23: __gnu_cxx::new_allocator<std::_Rb_tree_node<std::pair<int const, std::string> > >::deallocate(std::_Rb_tree_node<std::pair<int const, std::string> >*, unsigned long) (in /home/thm/test/test)
==723953== by 0x401C99: std::_Rb_tree<int, std::pair<int const, std::string>, std::_Select1st<std::pair<int const, std::string> >, std::less<int>, std::allocator<std::pair<int const, std::string> > >::_M_put_node(std::_Rb_tree_node<std::pair<int const, std::string> >*) (in /home/thm/test/test)
==723953== by 0x401AA6: std::_Rb_tree<int, std::pair<int const, std::string>, std::_Select1st<std::pair<int const, std::string> >, std::less<int>, std::allocator<std::pair<int const, std::string> > >::_M_destroy_node(std::_Rb_tree_node<std::pair<int const, std::string> >*) (in /home/thm/test/test)
==723953== by 0x401729: std::_Rb_tree<int, std::pair<int const, std::string>, std::_Select1st<std::pair<int const, std::string> >, std::less<int>, std::allocator<std::pair<int const, std::string> > >::erase(std::_Rb_tree_iterator<std::pair<int const, std::string> >) (in /home/thm/test/test)
==723953== by 0x40134C: std::map<int, std::string, std::less<int>, std::allocator<std::pair<int const, std::string> > >::erase(std::_Rb_tree_iterator<std::pair<int const, std::string> >) (in /home/thm/test/test)
==723953== by 0x401170: A::deleteMap() (in /home/thm/test/test)
==723953== by 0x400F4B: main (in /home/thm/test/test)
==723953== 
==723953== 
==723953== HEAP SUMMARY:
==723953== in use at exit: 0 bytes in 0 blocks
==723953== total heap usage: 10 allocs, 10 frees, 370 bytes allocated
==723953== 
==723953== All heap blocks were freed -- no leaks are possible
==723953== 
==723953== For counts of detected and suppressed errors, rerun with: -v
==723953== ERROR SUMMARY: 8 errors from 2 contexts (suppressed: 6 from 6)

Why?

此代码可以实现功能要求,但是健壮性并不好,假设在map.erase之后再次使用map当前的iterator,即

void deleteMap()
{
for (myMap::iterator it = map.begin(); it != map.end(); ++it)
{
map.erase(it->first);
std::cout << "map.first=" << it->first << " map.second=" << it->second << std::endl;
}
}

代码运行就会出现错误,因为it目前指向的对象已经被删掉了。

为了避免程序出现这样的错误,我们应该保证在iterator指向的对象被删掉之前,iterator已经向前移位一。

程序改成如下即可:

void deleteMap()
{
for (myMap::iterator it = map.begin(); it != map.end();)
{
map.erase(it++->first);
}
} 


void deleteMap()
{
for (myMap::iterator it = map.begin(); it != map.end();)
{
int i = it->first;
++it;
map.erase(i);
}
}

以上所述是小编给大家介绍的for循环中删除map中的元素valgrind检测提示error:Invalid read of size 8 ,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对小牛知识库网站的支持!

 类似资料:
  • 问题内容: 我有一个清单 我想在如下所示的for循环中删除此列表中的元素: 但这是行不通的。我能做什么? 问题答案: 使用循环遍历列表时,不允许从列表中删除元素。 重写代码的最佳方法取决于你要执行的操作。 例如,你的代码等效于: 另外,你可以使用while循环: 我正在尝试删除符合条件的项目。然后我转到下一个项目。 你可以将每个不符合条件的元素复制到第二个列表中: 或者,你可以使用filter或列

  • 问题内容: 从切片中删除元素(保留顺序)的惯用方法似乎是: 我想知道哪种循环内最好的方法。据我了解,不可能在以下范围内使用它: 但是可以使用。[编辑:这不起作用,请参见下面的答案] 是否有比使用or 更好或更惯用的方式? 问题答案: 您建议的解决方案不正确。问题是,当您从切片中删除一个元素时,所有后续元素都会 移位 。但是循环并不知道您更改了基础切片,并且循环变量(索引)照常增加,即使在这种情况下

  • 我当前正在将一个ArrayList转换为一个字符串,以便将其发送到一个DB,这样我就可以在另一端检索它,并稍后将其转换回一个ArrayList。 我的思路是通过执行以下操作将其转换为当前的字符串 是ArrayList,看起来如下所示: 当我查看数据库时,它看起来像这样 如何删除开头的和最后的以便在数据库上看起来像? 在另一端,我可以使用以下方法获得它: (我正在使用SQLite,这是我大学项目的一

  • 我有这个代码: outlets是传递给方法的ArrayList;riverBasin是int(int[]riverBasin)的2D“矩阵”; 从ArrayList outlets中删除“项”会生成错误: 但我并不完全理解。然而,我怀疑我弄坏了迭代器。对的那么我如何删除ArrayList中不需要的元素呢。 提前感谢您的帮助, 里卡多

  • 问题内容: 我试图设置获取所有元素的ID 。我写了以下代码: 但是我在控制台中得到以下输出: 这不是我所期望的。为什么第二个控制台输出却第一个控制台输出是? 问题答案: 在回答原始问题时,您使用不正确。在您的代码中,是索引。因此,要从伪数组中获取值,就必须这样做,而要获取id,就必须这样做。但是,首先不应该这样做。 摘要 永远不要使用来迭代nodeList或HTMLCollection。避免它的原

  • 我知道不建议在迭代时从列表中删除元素。 您最好使用iterator.remove()、java流,或者将remove复制到外部列表中。 但这段简单的代码正好起作用: 使用安全吗?