machinus
machinus

Reputation: 175

C++ : Clearing nested vectors leads to strange result

I tried to clear() a nested vector and instead of being cleared, the vector filled all the memory of my computer. Here is a code to reproduce the behaviour :

#include <iostream>
#include <vector>

using namespace std;

main(int argc, char* argv[]){   
    int d, j;
    int D = 2;
    vector<int> N = {2,2};  
    vector<vector<vector<int>>> v;

    v.resize(D);
    for(d = 0; d < D; d++)
            v[d].resize(N[d]);

    v.clear();
    for(d = 0; d < D; d++)
        for(j = 0; j < N[d]; j++)
            cout << "d : " << d << ", j : " << j << ", v[d][j].size() : " << v[d][j].size() << endl;
}

I'm using gcc version 5.4.1 on a x86_64-linux-gnu and compile with

g++ -std=c++17 freeing_vector.cpp && ./a.out

where freeing_vector.cpp is the code i gave before. The output is the following :

d : 0, j : 0, v[d][j].size() : 0
d : 0, j : 1, v[d][j].size() : 0
d : 1, j : 0, v[d][j].size() : 18446744073707429092
d : 1, j : 1, v[d][j].size() : 0

Now the fun part : please verify that removing v.clear() gives the expected result. Then try to change the content of N with D different numbers, for instance

N = {3, 4};

On my computer it leads to no mistake. In general, whatever is D, it seems to me that if N contains a least two equals elements, this strange beahaviour happened. So two questions : Do you observe the same behaviour on your computer ? Do you understand why ?

Upvotes: 1

Views: 426

Answers (2)

Felix Glas
Felix Glas

Reputation: 15534

std::vector::clear will destruct all elements:

Removes all elements from the container.

Invalidates any references, pointers, or iterators referring to contained elements. Any past-the-end iterators are also invalidated.

You can't access data past the end of the vector and expect anything sane to happen. This is clearly UB.

Accessing unallocated data can result in returning 0. However, there are no guarantees as to what will happen when code is exhibiting UB. There's no use in reasoning about how accessing the data in different ways gives different results, it's completely nondeterministic.

Try iterating over the vectors using bounds-checked code, e.g.:

std::vector<std::vector<std::vector<int>>> v(2, std::vector<std::vector<int>>(2, std::vector<int>{}));
//v.clear();
for (auto&& v1 : v) {
    for (auto&& v2 : v1) {
        std::cout << v2.size() << std::endl;
    }
}

Now, uncomment the clear() statement and see how many printouts you get.

Upvotes: 2

pm100
pm100

Reputation: 50230

you clear your vector and then try to iterate over it using indexing. What do you expect to happen? Try using v.at(x) instead if v[x] and see what happens

Upvotes: 1

Related Questions