-3

I've received a task in my university, which is to write a smart pointer. I need to upload the code to their server which runs some automated tests on it, and I've got only one error: memory access problem (null pointer or the like). Now I'am suspicious of my *, -> operator overloadings, which I think could crash if my raw_pointer would be NULL and I've tried NULL guarding them but then again I don't know what to return if this is the case. If this is not the case, then I really am helpless in this situation.

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

public:
    my_pointer() : raw_pointer(NULL) { }

    my_pointer(T *pointer) : raw_pointer(pointer) {
        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 (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 != NULL && raw_pointer->decRefCnt() == 0) {
         delete raw_pointer;
     }
}

};

When I do something like this:

// T = refcounted
my_pointer<refcounted> obj1;    
refcounted p = *obj1;

My program exits with exit code -1073741819 (0xC0000005). Thanks in advance!

masm64
  • 1,222
  • 3
  • 14
  • 31
  • 2
    You seem to be dereferencing a null pointer by writing `*obj1`. Make it manage an object first? – M.M Nov 02 '15 at 00:05
  • That's a weird approach to implement a _smart pointer_. – πάντα ῥεῖ Nov 02 '15 at 00:05
  • What exactly are the requirements of your "smart pointer"? – Philipp Nov 02 '15 at 00:06
  • It needs to support dereferencing, ->, implicit conversion to a raw pointer, ==, != operators need to be supported, reference counting is done by the object that is being referenced and not by the smart pointer, needs to have several constructors – masm64 Nov 02 '15 at 00:10
  • `T* operator->() { return raw_pointer; }` I think there is an error here. But this is not the reason of the crash, this was given by @M.M – A.S.H Nov 02 '15 at 00:14
  • Aside: you should use `nullptr` rather than `NULL`. –  Nov 02 '15 at 00:16
  • I would if I could, but sadly the compiler does not support C++11. How can I make my program not crash when something like this happens (dereferencing a null pointer)? – masm64 Nov 02 '15 at 00:18
  • @A.S.H What would be the error there? The implementation is wrong? – masm64 Nov 02 '15 at 00:19
  • @A.S.H `*obj` invokes `operator*`, not `operator->` – M.M Nov 02 '15 at 00:25
  • @masm64 there is no way to place an ambulance at the bottom of the cliff in C++. Instead, you need to make sure that your code never executes the dereferencing of a null pointer. In this case the options are: (a) don't write `*obj1` when you haven't got `obj1` managing an object; or (b) make the `operator*` function test if it is managing `nullptr` and throw an exception if so – M.M Nov 02 '15 at 00:26
  • masm64 and @M.M, forget about it, sorry. – A.S.H Nov 02 '15 at 00:30
  • Alternatively to what @M.M said, if you dont want to throw exceptions, you could make the (default) constructor private, and remove the constructor from a raw pointer . The only available constructors should be either on a object instance or another smart pointer. – A.S.H Nov 02 '15 at 00:34
  • @A.S.H typically, a smart pointer will allow for the pointer to "unmanage" the object so this problem could still arise. – M.M Nov 02 '15 at 00:36
  • @M.M this would be explicitly the responsibility of the user, but a typical user who wants to use only smart pointers must be given the guarantee that they are always valid. what do you think? It is a little bit similar to the reference in C++... – A.S.H Nov 02 '15 at 00:39

1 Answers1

2

Class implementation looks fine, but you have error in second code block.

obj1 is initialized with NULL pointer and in second row you dereference it and copy to new variable. So it crash.

You must assign something to obj1 either before dereferencing or check it for NULL.

For example like this

// T = refcounted
refcounted p0;
my_pointer<refcounted> obj1(&p0);    
refcounted p = *obj1;

or like this

// T = refcounted
my_pointer<refcounted> obj1;
refcounted p;
if( obj1 != NULL )
{
    p = *obj1;
}
Michael Nastenko
  • 2,785
  • 1
  • 10
  • 14