Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Segmentation Fault when deleting a pointer in vector

Im trying do delete a object pointer in a vector when a user wants to delete an object. Im trying to:

  1. Delete the pointer
  2. Remove the pointer from the vector

I have in a DataBase class a map of strings to vectors. And the vectors are containing pointers to objects. Like this:

Definition of objectMap and objectector in "database.h"

private:
    typedef std::vector<Object *> objectVector;
    typedef std::map<std::string, objectVector> objectMap;
    objectMap objects;

Implementation of deleteId in "database.cpp"

bool DataBase::deleteId(int id)
{
    // vectors
    for(objectMap::iterator vec = objects.begin(); vec != objects.end(); ++vec)
    {
        objectVector v = vec->second;
        // objects
        for(objectVector::iterator obj = v.begin(); obj != v.end(); ++obj)
        {
            if((*obj)->getId() == id)
            {
                delete *obj;  // pointer
                *obj = 0;
                v.erase(obj); // erase from vector
                modified = true;
                return true;
            }
        }
    }
    return false;
}

Im currently trying to the debug the program, and I am printing out the whole map of objects to see if the deletion worked. The problem is that the object pointer is still there after the deletion even if the function confirmed the deletion (i.e returned true). Can someone please explain whats going on?

like image 988
patriques Avatar asked Jun 19 '26 14:06

patriques


2 Answers

objectVector v = vec->second;

This copies the vector by value and thus you're referring to the copy, not to the real vector.

Suggesting to change that line into

objectVector& v = vec->second; // Reference to the "real" vector

No problems in invalidating your obj iterator since you're quitting the function as soon as you encounter the deletion element.

like image 75
Marco A. Avatar answered Jun 21 '26 03:06

Marco A.


Your code is wrong at least because you did not erase an element in the original vector. Use reference to the vector

for(objectMap::iterator vec = objects.begin(); vec != objects.end(); ++vec)
{
    objectVector &v = vec->second;

Also consider an approach when if after the erasing of an element in a vector the vector becomes empty then maybe you shoulod also erase the corresponding element in the map.

For example )without testing)

bool DataBase::deleteId(int id)
{
    bool modified = false;

    for ( auto it1 = objects.begin(); !modified && it1 != objects.end(); ++it1 )
    {
        auto it2 = std::find_if( it1->second.begin(), it1->second.end(),
                                 [&]( Object *o ) { return ( o->getId() == id ); } );
        modified = it2 != it1->second.end();

        if ( modified )
        {
            delete *it2;
            it1->second.erase( it2 );
            if ( it1->second.empty() ) it1 = objects.erase( it1 );
        }
    }

    return modified;
}
like image 33
Vlad from Moscow Avatar answered Jun 21 '26 04:06

Vlad from Moscow



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!