error: double free or corruption (out)

Sep 23, 2019 at 1:20pm
Hello
i have this code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <vector>
#include <algorithm>
#include <iostream>

int main(){
    std::vector<int> vec{0, 1, 2};
    std::vector<int>::iterator it = std::max_element(vec.begin(), vec.end());
    std::vector<int> vec2{3, 4, 5};
    vec.insert(vec.end(), vec2.begin(), vec2.end());
    vec.erase(it);
    for (auto &n : vec){
        std::cout << n << std::endl;
    }
}


but when i execute it, I get this output:
1
2
3
4
5
double free or corruption (out)
Aborted


first question: why this corruption error and how to fix it?
second: why is the output "1 - 2 - 3 - 4 - 5", and not "0 - 1 - 3 - 4 - 5"!? since the iterator "it" points to the max value in vec, I would expect to value 2 being erased, not 0.
I'm using g++ (Debian 9.2.1-8) 9.2.1 20190909
and for some reason, if I execute this code online (in cpp.sh), I get no errors about memory corruption, but the output is still wrong.

what could be wrong? thanks for the help!
Last edited on Sep 23, 2019 at 1:23pm
Sep 23, 2019 at 1:35pm
http://www.cplusplus.com/reference/vector/vector/insert/
Iterator validity
If a reallocation happens, all iterators, pointers and references related to the container are invalidated.
Sep 23, 2019 at 1:36pm
vector.insert can invalidate iterators. Using this invalid iterator is like using an invalid pointer; undefined behavior.

See: https://en.cppreference.com/w/cpp/container/vector/insert
cppreference wrote:
Causes reallocation if the new size() is greater than the old capacity(). If the new size() is greater than capacity(), all iterators and references are invalidated. Otherwise, only the iterators and references before the insertion point remain valid. The past-the-end iterator is also invalidated.
Last edited on Sep 23, 2019 at 1:37pm
Sep 23, 2019 at 1:39pm
The problem is line 7. After a vector is modified you cannot use the iterator proviously obtained.

Instead of using the iterator you may use the distance (which does not change):

http://www.cplusplus.com/reference/iterator/distance/?kw=distance
Sep 23, 2019 at 1:45pm
geez... is it invalidated because the vector is moved in memory when the size changes?

so is there any way to keep a reference to number 2 in this case? using deque would be the way, or is there any better approach?
thanks
Sep 23, 2019 at 1:48pm
Use std::distance as coder777 said, or, simply move line 10 above line 9.
Keeping references to an element of a vector that is changing in size is asking for trouble.
There are other solutions, but it all depends on the use case. For example, in a program I have, I have a dynamically growing vector objects, where each object can contain an array. I actually dynamically allocate each element and have my vector be a vector of pointers. But that might be overkill depending on the application.
Last edited on Sep 23, 2019 at 1:50pm
Sep 23, 2019 at 2:06pm
okk, I see.. thanks everybody for the help :)
Sep 23, 2019 at 2:15pm
One could make sure that the vector does not need realloc during the insert:
1
2
3
4
5
std::vector<int> vec{0, 1, 2};
std::vector<int> vec2{3, 4, 5};
vec.reserve( vec.size() + vec2.size() );
std::vector<int>::iterator it = std::max_element( vec.begin(), vec.end() );
vec.insert( vec.end(), vec2.begin(), vec2.end() );


One could seek the max from the elements of the first vector:
1
2
3
4
5
std::vector<int> vec{0, 1, 2};
std::vector<int> vec2{3, 4, 5};
auto first = vec.size();
std::vector<int>::iterator it = std::max_element( vec.begin(), vec.begin() + first );
vec.insert( vec.end(), vec2.begin(), vec2.end() );
Topic archived. No new replies allowed.