Search code examples
c++vectorstderasedouble-free

I meets double free error when I erase my vector in c++


As the following code.

I want to move the element in vector to back.

eg: [(1),2,3,4] -> [2,3,4,(1)]

But, it cause double free problem. The logic in this code is simple.

I think I misuse the erase function. Is it true? Would anyone tell me the detail?

Thanks for your reading.

This is output:

*** Error in '/home/ubuntu/workspace/hello-cpp-world.cc.o': double free or corruption (out): 0x00000000016ffca0 ***

This is the code snippet:

#include <iostream>
#include <vector>

int main() {
    std::vector<int*> targets;

    int* a = new int;
    *a = 1;
    int* b = new int;
    *b = 2;
    targets.push_back(a);
    targets.push_back(b);
    int i =0;
    for (std::vector<int*>::iterator obj1 = targets.begin(); obj1 != targets.end(); i++)
    {
        if(i==0)
        {
            int* tmp = *obj1;
            targets.push_back(tmp);
            targets.erase(obj1);
        }
        else obj1++;
    }

}

Solution

  • Invoking push_back or erase to std::vector may invalidate iterators. It is easier to use indexes.

    #include <iostream>
    #include <vector>
    
    int main() {
        std::vector<int*> targets;
    
        int* a = new int;
        *a = 1;
        int* b = new int;
        *b = 2;
        targets.push_back(a);
        targets.push_back(b);
        int i =0;
        for(size_t obj1 = 0; obj1 < targets.size(); i++)
        {
            if(i==0)
            {
                int* tmp = targets[obj1];
                targets.push_back(tmp);
                targets.erase(targets.begin() + obj1);
            }
            else obj1++;
        }
    
    }
    

    Since obj1 isn't used other than incrementing except for when i==0, you can write more simply

    #include <iostream>
    #include <vector>
    
    int main() {
        std::vector<int*> targets;
    
        int* a = new int;
        *a = 1;
        int* b = new int;
        *b = 2;
        targets.push_back(a);
        targets.push_back(b);
    
        int* tmp = targets[0];
        targets.push_back(tmp);
        targets.erase(targets.begin());
    
    }