-
Notifications
You must be signed in to change notification settings - Fork 120
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
it = map.erase(it) potentially passes entries twice #20
Comments
Hello, Thank you very much for the report. I effectively completely missed that when implementing the backward shift deletion. I started the implementation of a fix in the fix_issue_20 branch. I still have to check a bit if everything works fine and improve the documentation before merging the changes. Basically I check if I wrap around during the backward shift deletion and if it's the case i just return Thibaut |
I think simply checking for a wrap around is not enough. E.g when you insert 3 elements at location 30, 2 elements are at the end and one will wrap around. When erasing the second to last, backward shift will wrap around but there is still one element left to be iterated |
Effectively I went a bit too fast with the proposed solution, it will not work in multiple cases. I'll check this evening to see how we can do that. |
Hi, I checked a bit and currently I see the following possible solutions:
The problem is more complex than expected and I have to think a bit if I can find another solution or which solution to pick-up. Thibaut |
I also thought about adding an overflow buffer at the end. This might have a slight performance advantage because less need to Your iterator idea brings me to a new idea: How about instead of a reference, add a counter of the number of remaining items. |
Adding a counter would also be possible but the problem is that you also need to initialize it in other methods than I also realised that a reference to the last element is not really possible either as it may be invalidated. It also has the same problem as with a counter, how do you efficiently get a reference to the last element in some methods? You could eventually maintain a pointer to the last element in the class and update it on each insert/erase. But it's getting quite complex. |
I've stumbled upon a bug in my robin_hood map which also uses backward shift deleting, and wondered how you solve this issue in
tsl::robin_map
, and it seems you have exactly the same issue. (see martinus/robin-hood-hashing#42)The problem is that due to backward shift deleting, when iterating a map and erasing elements, it is possible that the same elements will be iterated over twice.
Here is a reproducer, where I insert two elements into the map. When erasing the second element, the first element will wrap around and be iterated over a second time. I currently think it is best to just claim that's the way it is, because I am afraid there is no easy workaround (except not using backward shift deleting)
I wonder what you think about that issue?
The text was updated successfully, but these errors were encountered: