Home > Net >  Wrappers and Access Violation
Wrappers and Access Violation

Time:01-04

Here is my problem : I created a generic wrapper class to handle memory management for some other classes I have where i have implemented a clone method which is supposed to clone the object by providing a new object (and new pointer to it) :

template <class T>
class Wrapper
{
public :
    Wrapper() { DataPtr = 0; }

    Wrapper(const T& inner) 
    { 
        if (DataPtr != 0)
            DataPtr = inner.clone();
        else
            DataPtr = 0;
    }

    ~Wrapper()
    {
        if (DataPtr != 0)
            delete DataPtr;
    }

    Wrapper& operator=(Wrapper& original)
    { 
        if (this != &original) 
        {
            delete DataPtr;
            DataPtr = DataPtr = 0 ? 0 : original.DataPtr->clone();
        }
        return *this;
    }

    T& operator*()
    {
        return *DataPtr;
    }

    T* operator->() 
    {
        return DataPtr;
    }

    const T& operator*() const
    {
        return *DataPtr;
    }

    const T* operator->() const
    {
        return DataPtr;
    }

private :
    T* DataPtr;
};

Say I have a Class that uses in it's private attributes Wrapper < Class2 > Obj; which has a clone method :

my issue is that trying to call any member using the overloaded access operator -> gives me : Exception thrown at 0x00007FF6122D4102 in Training.exe: 0xC0000005: Access violation reading location 0xFFFFFFFFFFFFFFFF.

And I don't understand why I don't have access since DataPtr is a member of the Wrapper Class

Both dereferencing the wrapper by doing (*Obj).SomeMethod() and using the -> operator by doing Obj->SomeMethod() give the same results.

CodePudding user response:

So the issue after all was that my operator= overload had a problem: After deleting DataPtr, I tried checking if DataPtr was null while it didn't exist. What I should do, instead, is check if the DataPtr of the object I want to assign (i.e. original) was null.

Below is the corrected code :

template <class T>

class Wrapper
{
public:
    Wrapper() { DataPtr = 0; } // the default constructor which point to nothing
    Wrapper(const T& inner) // constructor
    {
        DataPtr = inner.Clone();
    }
    ~Wrapper()
    {
        delete DataPtr;
    }

    Wrapper(const Wrapper<T>& original) // copy constructor when pass in a Wrapper class
    {
        if (original.DataPtr != 0)
            DataPtr = original.DataPtr->Clone();
        else
            DataPtr = 0;
    }

    // return by reference to avoid unnecessary copy
    Wrapper& operator= (const Wrapper<T>& oringinal)// overloading "=" assignement operator
    {
        if (this != &oringinal)
        {
            if (DataPtr != 0)
            {
                delete DataPtr;
                DataPtr = (oringinal.DataPtr != 0) ? oringinal.DataPtr.Clone() : 0;
            }

        }
        return  *this; // return what this point to
    }

    // two version of dereferencing operator *
    // dereference both const and non-const objects
    T& operator*() // overloading "*" to get object from pointer
    {
        return *DataPtr;
    }

    const T& operator*() const // return a const object
    {
        return *DataPtr;
    }

    // overloading "->" to access method within pointed object
    const T* operator ->() const
    {
        return DataPtr;
    }

    T* operator ->()
    {
        return DataPtr;
    }


private:
    T* DataPtr;
};
  • Related