0

I use std::multimap.lower_bound method to return ranged result. But in the same content of container, sometimes I got the wrong iterators pair and it crash my program. I can see the content in container with visual studio, they are all correct. And I use multimap's find method, it also worked well. It just returns the damned invalid iterators pair and crash my program, and most important of that, I can't do any test to skip that situation. What's wrong with this situation?

My example codes as follows:

std::multimap<std::string,std::string>::iterator it = tagged_files.lower_bound("vocal");
std::multimap<std::string,std::string>::iterator it_end = tagged_files.upper_bound("vocal");

For the most part, they worked well. When I print it and it_end with %p(using printf), their results are 8f98ab9(one pointer value) and 0(same key). When I got invalid iterators, debug messages would shows 8f98ab9(same value) and 2b8a839(strange value).

Besides,the size of tagged_files is always the same. No item was inserted at all during whole session even invalid iterators are received. It also proved by printf %d with tagged_files.size().

naive231
  • 1,360
  • 1
  • 11
  • 28
  • 4
    without seeing any code it will be difficult to help you out. try to write a simple program that shows and exemplifies your problem, and you'll get a good answer quickly ;) – Castilho Oct 17 '12 at 11:14
  • 2
    If you use `std::multimap` correctly, then it will only return valid iterators. Thus, you are not using `std::multimap` correctly. Since we can't see what you do in your code, we can't say *what* you are doing wrong – jalf Oct 17 '12 at 11:18
  • I put my sample code on, and I prove that I don't verify any content in multimap at all, including insert or erase actions. – naive231 Oct 17 '12 at 12:10
  • 1
    You have a bug in your code. You've showed us two lines, which are OK. Therefore the bug is somewhere in the rest of the code. – john Oct 17 '12 at 12:24
  • Everybody misunderstands the question behind the code. The question is why `lower_bound` or `upper_bound` **returns the wrong iterators.**. Modification anything in `lower_bound` or `upper_bound` implementation is impossible. – naive231 Oct 17 '12 at 12:51
  • 2
    Let me be plain. `lower_bound` does not return the wrong iterators. You must be using it wrong. Do you really think if there was a bug in `lower_bound` so that it returned the wrong iterators, you would have been the first to find it? – John Dibling Oct 17 '12 at 12:58

1 Answers1

2

When I have an invalid iterator with a std container like map, multimaps, 90% of the time, the reason is I am iterating over the container while I am removing items in this container.

As soon as an item is removed (or even insterted in some other containers) in a container, the valid state of iterators is no longer guaranteed.

edit: like the comments below say, rules of invalidation of iterators vary from container to container. cf this question

edit2: you don't show us how you dereference your iterators. Your iterator is a std::pair, and you should check the returned iterator is not equal to yourContainer.end() before you derefence it. But since you don't show us the code where you derefence the iterator it is hard to tell. you don't show us neither the way you output your traces.

Community
  • 1
  • 1
Stephane Rolland
  • 38,876
  • 35
  • 121
  • 169
  • good thing that built-in collections in Java have a concurrent modification detection, then? :-) – John Dvorak Oct 17 '12 at 11:47
  • 1
    For std::map and std::multimap, only iterators pointing to the element being removed are invalidated. All others remain valid. The iterator invalidation rules vary from container to container. – Dave S Oct 17 '12 at 11:50
  • This is probably the case; or a write to the memory that makes up the container. – rioki Oct 17 '12 at 11:51
  • 1
    @Dave S that is true did not know that... Google points us back to a stackoverflow question: http://stackoverflow.com/questions/6438086/iterator-invalidation-rules – rioki Oct 17 '12 at 11:55
  • Everybody misunderstands the question behind the code. The question is why `lower_bound` or `upper_bound` **returns the wrong iterators.**. Modification anything in `lower_bound` or `upper_bound` implementation is impossible. – naive231 Oct 17 '12 at 12:53
  • you don't show how you dereference your iterators. your iterator is a std::pair, and should not be equal to yourContainer.end() before you derefence it. – Stephane Rolland Oct 17 '12 at 13:58