Correctly delete pointers in std::list allocated elsewhere

Casey picture Casey · Jul 17, 2011 · Viewed 8.5k times · Source

Possible Duplicate:
Does std::list::remove method call destructor of each removed element?

I have a SpriteHandler class that allows the user to register a pointer to a Sprite object for drawing, all it does is access methods on the object. I wanted to write a safety catch that automatically deleted the memory associated with the pointers if the user forgot to do so by the end of the program (and it's less to worry about for the user too!) :

 

//SpriteHandler.h
class SpriteHandler {
public:
//...
    void RegisterObject(Sprite* object);
    bool IsRegistered(Sprite* object);
    void UnregisterObject(Sprite* object);
private:
//...
    static std::list<Sprite*>* _sprite = NULL;
};

//SpriteHandler.cpp
std::list<Sprite*>* SpriteHandler::_sprites = NULL;


void SpriteHandler::RegisterObject(Sprite* object) {
    if(object == NULL) return;
    if(_sprites == NULL) _sprites = new std::list<Sprite*>();
    _sprites->push_back(object);
    _sprites->sort(UDLessSprite);
}

bool SpriteHandler::IsRegistered(Sprite* object) {
    return std::binary_search(_sprites->begin(), _sprites->end(), object);
}

void SpriteHandler::UnregisterObject(Sprite* object) {
    if(object == NULL) return;
    if(IsRegistered(object) == false) return;

    _sprites->remove(object);
    if(_sprites->size() <= 0) {
        if(_sprites) {
            _sprites->clear();
            delete _sprites;
            _sprites = NULL;
        }
        return;
    }
    _sprites->sort(UDLessSprite);
}

void SpriteHandler::Release() {
    if(_sprites) {
        std::list<Sprite*>::iterator _iter = _sprites->begin();
        while(_iter != _sprites->end()) {
            delete (*_iter);
            (*_iter) = NULL;
            ++_iter;
        }
        _sprites->clear();
        delete _sprites;
        _sprites = NULL;
    }
}

 

The issue I"m having is that after the first pointer is deleted the next iterator is pointing to an already freed object (memory location is 0xfeeefeee).

How would I correctly iterate through them, deleting each one?

Answer

Alok Save picture Alok Save · Jul 17, 2011

If you want safety and implicit resource cleanup, do not use raw pointers, use smart pointers!

The problem with STL containers is:
If the contained object is a pointer STL containers DO NOT take ownership of destroying it. You will have to explicitly call delete on each contained pointer to delete the content it is pointing to.

Have a look at this similar question here.

The best way to go about this is not storing raw pointers inside STL containers but using their intelligent cousins smart pointers instead(boost::shared_ptr) Check out the Boost documentation, These pointer cousins are intelligent enough to deallocate themselves when there is no one referring to them and saves you the problems like the one you are facing now.