c++ - std::map iterate and delete valgrind errors -
i have simple program deletes items in std::map while iterating on map. if not wrong forward iterators not invalidated erase in map. valgrind throws invalid read errors. can explain why.
#include <map> #include <iostream> typedef std::map<std::string, int> sourcemap; int main(int argc, char *argv[]) { sourcemap sourcemap; sourcemap["item1"] = 1; sourcemap["item2"] = 2; sourcemap["item3"] = 3; sourcemap["item4"] = 4; for(sourcemap::const_iterator it=sourcemap.begin(); != sourcemap.end(); ++it) { sourcemap.erase(it->first); } }
valgrind errors:
==31703== invalid read of size 8 ==31703== @ 0x3851069e60: std::_rb_tree_increment(std::_rb_tree_node_base*) (in /usr/lib64/libstdc++.so.6.0.13) ==31703== 0x4013d6: std::_rb_tree_const_iterator<std::pair<std::string const, int> >::operator++() (stl_tree.h:259) ==31703== 0x40106b: main (map_iterator.cpp:14) ==31703== address 0x4c2c0b8 24 bytes inside block of size 48 free'd ==31703== @ 0x4a0545f: operator delete(void*) (vg_replace_malloc.c:387) ==31703== 0x402821: __gnu_cxx::new_allocator<std::_rb_tree_node<std::pair<std::string const, int> > >::deallocate(std::_rb_tree_node<std::pair<std::string const, int> >*, unsigned long) (new_allocator.h:95) ==31703== 0x402103: std::_rb_tree<std::string, std::pair<std::string const, int>, std::_select1st<std::pair<std::string const, int> >, std::less<std::string>, std::allocator<std::pair<std::string const, int> > >::_m_put_node(std::_rb_tree_node<std::pair<std::string const, int> >*) (stl_tree.h:363) ==31703== 0x4017d0: std::_rb_tree<std::string, std::pair<std::string const, int>, std::_select1st<std::pair<std::string const, int> >, std::less<std::string>, std::allocator<std::pair<std::string const, int> > >::_m_destroy_node(std::_rb_tree_node<std::pair<std::string const, int> >*) (stl_tree.h:384) ==31703== 0x4027ab: std::_rb_tree<std::string, std::pair<std::string const, int>, std::_select1st<std::pair<std::string const, int> >, std::less<std::string>, std::allocator<std::pair<std::string const, int> > >::erase(std::_rb_tree_iterator<std::pair<std::string const, int> >) (stl_tree.h:1348) ==31703== 0x401ff2: std::_rb_tree<std::string, std::pair<std::string const, int>, std::_select1st<std::pair<std::string const, int> >, std::less<std::string>, std::allocator<std::pair<std::string const, int> > >::erase(std::_rb_tree_iterator<std::pair<std::string const, int> >, std::_rb_tree_iterator<std::pair<std::string const, int> >) (stl_tree.h:1388) ==31703== 0x4016a7: std::_rb_tree<std::string, std::pair<std::string const, int>, std::_select1st<std::pair<std::string const, int> >, std::less<std::string>, std::allocator<std::pair<std::string const, int> > >::erase(std::string const&) (stl_tree.h:1374) ==31703== 0x40141c: std::map<std::string, int, std::less<std::string>, std::allocator<std::pair<std::string const, int> > >::erase(std::string const&) (stl_map.h:582) ==31703== 0x40105c: main (map_iterator.cpp:16) ==31703== ==31703== ==31703== heap summary: ==31703== in use @ exit: 0 bytes in 0 blocks ==31703== total heap usage: 8 allocs, 8 frees, 312 bytes allocated ==31703== ==31703== heap blocks freed -- no leaks possible
this has been discussed death. must not use invalid iterators. write this:
for(sourcemap::const_iterator = sourcemap.begin(); != sourcemap.end(); /* no hoist */ /* no increment */ ) { sourcemap.erase(it++); }
alternatively:
// before { = sourcemap.erase(it); }
alternatively yet (since don't have conditions on erasing):
sourcemap.clear();
Comments
Post a Comment