简体   繁体   中英

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 (ie returned true). Can someone please explain whats going on?

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.

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;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM