Skip to content

it = map.erase(it) potentially passes entries twice  #20

@martinus

Description

@martinus

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)

template <typename T>
struct BadHash {
    size_t operator()(T const& val) const {
        return static_cast<size_t>(val);
    }
};

int main(int, char**) {
    tsl::robin_map<int, int, BadHash<int>> map;
    map.reserve(16); // resizes with mask 31

    map.emplace(31, 1);        // gets into last bucket
    map.emplace(1024 + 31, 2); // would also get into last bucket, but wraps around

    // first entry in the map
    auto it = map.begin();
    std::cout << it->first << "->" << it->second << std::endl;

    // second entry in the map, erase it
    ++it;
    std::cout << it->first << "->" << it->second << std::endl;
    it = map.erase(it);

    // now all two elements are iterated, we should be at the map's end, but due to backward shift
    // deletion we are not
    if (it != map.end()) {
        std::cout << it->first << "->" << it->second << std::endl;
    }
    it = map.erase(it);
    std::cout << "are we now at the end? " << (it == map.end()) << std::endl;
}

I wonder what you think about that issue?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions