Search code examples
c++multithreadingvectorinsertexc-bad-access

Thread 1: EXC_BAD_ACCESS (code=1, address=0x0) on vector insert


I am trying to insert an element into a vector using the .insert(<#const_iterator __position#>, <#const_reference __x#>)

This is my code:

hpp:

typedef int elementType;

class Heap{
private:
    std::vector<elementType> myVecrtor;
    int mySize = 1; //The minimum size is 1 since the first element is a dummy.
    
public:
    Heap();
    void insert(elementType const item);
};

cpp:

void Heap::insert(elementType item){
    typename std::vector<elementType>::iterator it;
    for(int i = 0; i <= mySize; i++){
        it++;
    }
    myVecrtor.insert(it, item);
    mySize++;
}

When calling the method inside the main:

#include <iostream>
#include "Heap.hpp"

int main(int argc, const char * argv[]) {
    Heap h;
    h.insert(10);
}

The debugger gives me a successful run then gives me an error inside the vector hpp file:

void __construct_backward_with_exception_guarantees(_Alloc&, _Tp* __begin1, _Tp* __end1, _Tp*& __end2) {
    ptrdiff_t _Np = __end1 - __begin1;
    __end2 -= _Np;
    if (_Np > 0)
        _VSTD::memcpy(__end2, __begin1, _Np * sizeof(_Tp));//The error is given here
}

error:Thread 1: EXC_BAD_ACCESS (code=1, address=0x0)

I have no idea why I am getting this. Any help would be appreciated.


Solution

  • typename std::vector<elementType>::iterator it;
    

    This statement declares a vector iterator. As you can see here, it is completely uninitalized. It is not initialized to anything.

        for(int i = 0; i <= mySize; i++){
            it++;
        }
    

    And this sequence increments the iterator some unspecified number of times. Since it is not initialized, this is undefined behavior.

        myVecrtor.insert(it, item);
    

    Attempting to insert something into a vector using an iterator that has never been initialized, and after being not-initialized it gets incremented an unspecified amount of times, is not going to go very far.

    Heap's constructor is not shown, so it is unclear if its constructor initializes the vector's contents, in any form or fashion. But that seems unlikely and this mySize appears to be initialized to 1. Therefore this for loop will iterate at least once, and most likely not once but twice.

    If the vector is, indeed empty, then even if it is correctly initialized, its only possible valid value will be either begin() or end() (with both being equivalent for a completely empty vector). As such, incrementing the iterator, even if it's properly initialized, will be undefined behavior.

    To summarize, there are multiple conceptual flaws in the shown code:

    1. All iterators must be initialized before they can be used in any way, incremented or decrementing, dereferenced, or in any other way.

    2. The only possible valid iterator for a completely empty vector cannot be incremented or decremented.

    3. If insert()'s goal is to append a new value to a vector, nothing of what the shown code is doing is needed, in any form or fashion. That's because this just happens to be exactly what std::vector's very own push_back() does! No iterator, or incrementing is required!