c++pointerssmart-pointersdouble-free

Double free or corruption, why does this appear?


I've nearly finished my smart pointer (I know...) so I uploaded it to my univerity's website which runs a number of automated tests on my code. There are two things wrong with a number of tests:

The thing is I don't know what kind of tests are being excecuted. I am able to read the automated tests' stdout which I did, this is written there:

In instantiation of ‘my_pointer<T>::my_pointer() [with T = tester]’:
error: no matching function for call to ‘tester::tester()’
note: candidates are:
tester::tester(my_pointer<tester>)
candidate expects 1 argument, 0 provided
tester::tester(const tester&)
candidate expects 1 argument, 0 provided

So I'm guessing for some odd reason it won't invoke my my_pointer() constructor? This is my smart pointer class:

template<class T>
class my_pointer {
    T* raw_pointer;

public:
    my_pointer() {
        raw_pointer = new T();
        raw_pointer->incRefCnt();
    }

    my_pointer(T *obj) : raw_pointer(obj) {
        if(raw_pointer != NULL) raw_pointer->incRefCnt();
    }

    my_pointer(const my_pointer<T>& smart_pointer) : raw_pointer(smart_pointer.raw_pointer) {
        if(raw_pointer != NULL) raw_pointer->incRefCnt();
    }

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

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

    operator T*() {
        return raw_pointer;
    }

    my_pointer<T> &operator=(const my_pointer<T> &smart_pointer) {
        if(this != &smart_pointer && raw_pointer != NULL) {
            /** if this was the last reference to the given memory address */
            if (raw_pointer->decRefCnt() == 0) {
            delete raw_pointer;                    
            }

            raw_pointer = smart_pointer.raw_pointer;
            raw_pointer->incRefCnt();
        }

        return *this;
    }

    bool operator== (const T* pointer) {
        return raw_pointer == pointer;
    }

    bool operator!= (const T* pointer) {
        return raw_pointer != pointer;
    }

    bool operator== (const my_pointer<T> &smart_pointer) {
        return raw_pointer == smart_pointer.raw_pointer;
    }

    bool operator!= (const my_pointer<T> &smart_pointer) {
        return raw_pointer != smart_pointer.raw_pointer;
    }

    ~my_pointer() {
       if(raw_pointer->decRefCnt() == 0 && raw_pointer != NULL) {
           delete raw_pointer;
        }
    }
};

This is a class, in which the references can be counted:

class refcounted {
private:
    int count;
public:
    refcounted() : count(0) { }

    int incRefCnt() {
        return ++count;
    }

    int decRefCnt() {
        return --count;
    }
};

Can you see any problems with the code? Thanks in advance!


Solution

  • You are unconditionally deleting your raw pointer in the destructor. This is wrong. You must decrement the reference count, and only delete if it becomes zero.

    You also call raw_pointer->incRefCnt(); in several places without checking whether raw_pointer is NULL.