0

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++;
    }

}
Shawn Huang
  • 187
  • 2
  • 14

1 Answers1

3

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());

}
MikeCAT
  • 73,922
  • 11
  • 45
  • 70
  • Thanks for your answer. But one thing I don't understand. You say that `Invoking push_back or erase to std::vector may invalidate iterators.`. But I try to remove `push_back` or `erase`. It works. Would you tell me why these two lines can't exist at the same time? – Shawn Huang May 12 '16 at 05:49
  • 1
    @Shawn Huang reading the documentation of [`pushback`](http://en.cppreference.com/w/cpp/container/vector/push_back) and [`erase`](http://en.cppreference.com/w/cpp/container/vector/erase) might help. – Biruk Abebe May 12 '16 at 05:52
  • @bkVnet Thank you. I will test more cases when iterator is invalidated – Shawn Huang May 12 '16 at 05:59
  • I find the reference may improve the answer http://stackoverflow.com/questions/6438086/iterator-invalidation-rules. – Shawn Huang May 12 '16 at 06:19