Search code examples
c++vectorsegmentation-faultiterationerase

Why erasing element from vector while iterating causes Segmentation fault (core dumped)?


The following generates the problem I am having in a larger scale program.

#include <iostream>
#include <vector>

using namespace std;

int main()
{
    vector<int> vec{1, 2, 3, 4, 5};

    for (unsigned i = vec.size() - 1; i >= 0; --i) {
        if (vec[i] > 2) vec.erase(vec.begin() + i);
        else cout << vec[i] << "  ";
    }
    cout << endl;


    return 0;
}

This causes Segmentation fault (core dumped).

After a bit debugging, I found that changing the code the following way, "solves" the problem.

#include <iostream>
#include <vector>

using namespace std;

int main()
{
    vector<int> vec{1, 2, 3, 4, 5};

    for (unsigned i = vec.size() - 1; i >= 1; --i) {
        if (vec[i] > 2) vec.erase(vec.begin() + i);
        else cout << vec[i] << "  ";
    }
    if (vec[0] > 2) vec.erase(vec.begin());
    else cout << vec[0] << "  ";
    cout << endl;


    return 0;
}

This is printing what I expected to get.

2 1

Is not it what the for loop was doing in the first program? I just moved the condition for the beginning of the vector outside the loop!

Also what is the proper way to erase element from vector while iterating like so?


Solution

  • As the comment says, i is unsigned, therefore i >= 0 is always true. When i becomes less than 0 it actually becomes a large positive number, and then indexing into the vector with i invokes undefined behavior.

    The proper way to erase elements from a vector is to use the erase-remove-if idiom:

    vec.erase(std::remove_if(vec.begin(), vec.end(), [](int i) {
                return i > 2; }), vec.end());