Search code examples
c++pointersmemory-managementinvalidation

Invalidating deleted pointers?


template<typename T>
someclass<T>& operator=(const someclass<T>& other)
{
    typename std::vector<T *>::const_iterator rhs;
    typename std::vector<T *>::iterator lhs;

    //identity test
    //this->data is std::vector<T *>

    for(lhs = this->data.begin(); lhs != this->data.end(); lhs++)
    {
        delete *lhs;
    }

    this->data.clear(); // this is what I forgot

    this->data.reserve(other.data.size());
    for (rhs = other.data.begin(); rhs != other.data.end(); rhs++)
    {
        if (NULL == *rhs)
        {
            this->data.push_back(NULL);
        }
        else
        {
            this->data.push_back(new T(**rhs));
        }
    }
}

As you can see in the comments, I forgot to clear out the old pointers in the array. When I invoked the assignment operator for the second time, I got glibc error complaining about double free. The only information provided was the deleted address.

This make me thinking about what to do with such class of deleted pointers - when you don't want to delete them again, and when you do, it is certainly an error. You cannot set them to NULL, because another delete would be correct then. You don't want to keep the value as the memory location can be assigned to newly created object.

What would be good for debugging is some value, like INVALID, which you assign to these pointers saying "invoking delete on this pointer is an error", instead of NULL, which say "invoking delete on this pointer does nothing". Is there something like this?


Solution

  • The solution to this problem is to write code that does not contain any deletes. Use shared_ptr where possible. When you have a container that owns polymorphic objects, you can also use Pointer Container.