Crash Investigation – Part 3 – Memory issue by reference to member of vector

Introduction

In earlier blogs, I have discussed about the following scenarios where bad implementation causes the program to crash:

In this post, I point out another mistake that could be causing seg fault.

Concepts

According CPP Reference, C++ vector could be expanded, when the allocated memory is exhausted. Specifically, the vector will double its size from its previous capacity.

When memory allocation happens, the addresses of its items are changed. The following output the memory address of its member:

#include <iostream>
#include <vector>

using namespace std;

int main()
{
    vector<int> myVec;
    myVec.push_back(1);
    cout<<"addr of myVec= "<<&myVec<<" capacity= "<<myVec.capacity()<<endl;
    cout<<"addr of 1= "<<&myVec[0]<<endl;
    myVec.push_back(2);
    cout<<"addr= of myVec= "<<&myVec<<" capacity= "<<myVec.capacity()<<endl;
    for (int i = 0; i<myVec.size(); i++){
        cout<<"address of "<<i<<"= "<<&myVec[i]<<endl;
    }
    
    myVec.push_back(3);
    myVec.push_back(4);
    cout<<"addr of myVec= "<<&myVec<<" capacity= "<<myVec.capacity()<<endl;
    for (int i = 0; i<myVec.size(); i++){
        cout<<"address of "<<i<<"= "<<&myVec[i]<<endl;
    }

    myVec.push_back(5);
    myVec.push_back(6);
    cout<<"addr of myVec= "<<&myVec<<" capacity= "<<myVec.capacity()<<endl;
    for (int i = 0; i<myVec.size(); i++){
        cout<<"address of "<<i<<"= "<<&myVec[i]<<endl;
    }

    myVec.push_back(7);
    myVec.push_back(8);
    cout<<"addr of myVec= "<<&myVec<<" capacity= "<<myVec.capacity()<<endl;
    cout<<" NO CHANGE IN ADDRESS IF THERE IS NO REALLOCATION"<<endl;
    for (int i = 0; i<myVec.size(); i++){
        cout<<"address of "<<i<<"= "<<&myVec[i]<<endl;
    }
    
    myVec.push_back(9);
    cout<<"addr of myVec= "<<&myVec<<" capacity= "<<myVec.capacity()<<endl;
    for (int i = 0; i<myVec.size(); i++){
        cout<<"address of "<<i<<"= "<<&myVec[i]<<endl;
    }
    
    myVec.push_back(10);
    cout<<"addr of myVec= "<<&myVec<<" capacity= "<<myVec.capacity()<<endl;
    cout<<" NO CHANGE IN ADDRESS IF THERE IS NO REALLOCATION"<<endl;
    for (int i = 0; i<myVec.size(); i++){
        cout<<"address of "<<i<<"= "<<&myVec[i]<<endl;
    }
    
    return 0;
}
addr of myVec= 0x7fff9bf6f490 capacity= 1
addr of 1= 0x55ad67a77eb0
addr= of myVec= 0x7fff9bf6f490 capacity= 2
address of 0= 0x55ad67a782e0
address of 1= 0x55ad67a782e4
addr of myVec= 0x7fff9bf6f490 capacity= 4
address of 0= 0x55ad67a77eb0
address of 1= 0x55ad67a77eb4
address of 2= 0x55ad67a77eb8
address of 3= 0x55ad67a77ebc
addr of myVec= 0x7fff9bf6f490 capacity= 8
address of 0= 0x55ad67a78300
address of 1= 0x55ad67a78304
address of 2= 0x55ad67a78308
address of 3= 0x55ad67a7830c
address of 4= 0x55ad67a78310
address of 5= 0x55ad67a78314
addr of myVec= 0x7fff9bf6f490 capacity= 8
 NO CHANGE IN ADDRESS IF THERE IS NO REALLOCATION
address of 0= 0x55ad67a78300
address of 1= 0x55ad67a78304
address of 2= 0x55ad67a78308
address of 3= 0x55ad67a7830c
address of 4= 0x55ad67a78310
address of 5= 0x55ad67a78314
address of 6= 0x55ad67a78318
address of 7= 0x55ad67a7831c
addr of myVec= 0x7fff9bf6f490 capacity= 16
address of 0= 0x55ad67a78330
address of 1= 0x55ad67a78334
address of 2= 0x55ad67a78338
address of 3= 0x55ad67a7833c
address of 4= 0x55ad67a78340
address of 5= 0x55ad67a78344
address of 6= 0x55ad67a78348
address of 7= 0x55ad67a7834c
address of 8= 0x55ad67a78350
addr of myVec= 0x7fff9bf6f490 capacity= 16
 NO CHANGE IN ADDRESS IF THERE IS NO REALLOCATION
address of 0= 0x55ad67a78330
address of 1= 0x55ad67a78334
address of 2= 0x55ad67a78338
address of 3= 0x55ad67a7833c
address of 4= 0x55ad67a78340
address of 5= 0x55ad67a78344
address of 6= 0x55ad67a78348
address of 7= 0x55ad67a7834c
address of 8= 0x55ad67a78350
address of 9= 0x55ad67a78354

From the above program, we see that the capacity of the vector increases by twice the previous size: 2->4->8->16.
The memory addresses of its items changes each time the re-allocation occurs.

If we have a pointer or reference to a specific item in the vector, there the address of stored in the pointer or the reference itself becomes invalid. The exact behavior depends on the scenario and compiler implementation.

Sample faulty program

I have made the following mistake that was time-consuming to debug. I used reference to update a specific item in the array.

#include <iostream>
#include <vector>

using namespace std;

int main()
{
    vector<int> myVec;
    myVec.push_back(0);
    int &ref = myVec[0];
    myVec.push_back(1);
    myVec.push_back(2);
    myVec.push_back(3);
    myVec.push_back(4);
    myVec.push_back(5);
    
    cout<<"accessing ref="<<ref<<endl;
    return 0;
}

Running the program on www.onlinegdb.com, the output is a garbage value:

accessing ref=267256419

Garbage value is output because the compiler has not yet deallocated the memory. Had it do, seg fault error happens and the program crashes.

One thought on “Crash Investigation – Part 3 – Memory issue by reference to member of vector

Leave a Reply

Your email address will not be published. Required fields are marked *