0

When i run the following code I get a segfault on the 'find()' call.

#include <vector>
#include <unordered_map>

struct item {
    std::unordered_map<int,int> map;
};

int main(int argc, char** argv) {
   std::vector<item> stack;
   stack.emplace_back();
   std::unordered_map<int,int>& topmap=stack.back().map;
   stack.emplace_back();
   auto ind=topmap.find(5);
   if(ind!=topmap.end()) {
      printf("Found element five in second to top item\n");
   }
}

(compiled with -std=c++11)

However, if the second emplace_back() call is removed, there is no segfault.

Why is this? Am I using reference variables wrong? Does adding another element to the stack invalidate topmap?

Jeremy Salwen
  • 8,061
  • 5
  • 50
  • 73

3 Answers3

3

The most likely explanation is that the second call to emplace_back causes a re-allocation, invalidating topmap. You can easily check this by looking at stack.capacity(). If that changes between calls, there has been a re-allocation.

juanchopanza
  • 223,364
  • 34
  • 402
  • 480
2

If you read e.g. this reference, you will see the text

If the new size() is greater than capacity() then all iterators and references (including the past-the-end iterator) are invalidated."

Adding new items to the end of a vector typically reallocates the data inside the vector and causes this behavior. More specifically, since map is an ordinary instance inside the structure, it will too be reallocated.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
1

Does adding another element to the stack invalidate topmap?

Not mandatory, but it can. It depends if reallocation happened when std::vector::emplace_back() is called. std::vector::emplace_back documentation:

If the new size() is greater than capacity() then all iterators and references (including the past-the-end iterator) are invalidated. Otherwise only the past-the-end iterator is invalidated.

Slava
  • 43,454
  • 1
  • 47
  • 90