2

Possible Duplicate:
Problem with std::map::iterator after calling erase()

May be you could enlighten me with an issue I'm currently having. So problem is that I get a bad access memory when I'm trying to erase some elements in the map. We suppose the following typedef :

typedef std::map < std::string *, Document *, pStringCompare > Map;

And we suppose we already have instantiated a map which contains two elements (for example) before the execution of all the following code. This code with working great :

Map::iterator it = documents.begin();

std::string *s = it->first;
Document *d = it->second;

documents.erase(it);

delete d;
delete s;

But when I'm trying to loop with the iterator, i get the error.

for (Map::iterator it = documents.begin() ; it != documents.end() ; it++)
{
    std::string s = * ( it->first);
    Document dd = * (it->second);
    std::cout << s << " || " << dd;
    documents.erase(it);  // This line causes the bad access memory error.
}

Thanks for your help ! It's really appreciated !

Aleks

Community
  • 1
  • 1
Aleks
  • 410
  • 4
  • 22

2 Answers2

6

You are accessing invalidated iterator. Once you pass it to erase() it is no longer valid, so you cannot increment it in your for loop. See Iterator Invalidation Rules for more details on that.

Your loop should be structured like this to avoid accessing invalidated iterators:

for (Map::iterator it = documents.begin() ; it != documents.end() ; )
{
    std::string s = * ( it->first);
    Document dd = * (it->second);
    std::cout << s << " || " << dd;
    documents.erase(it++);
}

Though I really recommend you read more documentation and understand what is going on here. For example, see this.

Good Luck!

Community
  • 1
  • 1
1

Alternatively:

while ((Map::iterator iter = documents.begin()) != documents.end())
{
   std::string s = * ( iter->first);
   Document dd = * (iter->second);
   std::cout << s << " || " << dd;
   documents.erase(iter);
}
Ryan Guthrie
  • 688
  • 3
  • 11