Search code examples
c++c++11shared-ptrtr1

null shared_ptr can access to member functions


I can access member functions of a null shared_ptr object :

#include <memory>
#include <iostream>

class A
{
public:
    int getNum() {return 1234;}
};

int main()
{
    std::shared_ptr<A> pA(nullptr);
    std::cout << pA->getNum() << std::endl;
}

returns 1234 while I was expecting an exception. Same result happens for

std::shared_ptr<A> pA();

or

std::shared_ptr<A> pA();
pA.reset();

Is this really the expected behaviour ? If it is what is the corect shared_ptr defination that throws an exception in case of a member function call ?

Using VS2010.


Solution

  • Technically, what you did here does entail undefined behavior. However, because your getNum method is not virtual and makes no use whatsoever of this, it happens not to crash this time. To see why, imagine that the compiler internally rewrote your program like so:

    class A { };
    
    int A_getNum(A* this) { return 1234; }
    
    int main()
    {
      A* pA = 0;
      std::cout << A_getNum(pA) << '\n';
    }
    

    You can see that the null pointer is never dereferenced even though there is no actual A object, so it doesn't crash. The shared_ptr is irrelevant -- you'd get the same effect if you'd used a bare pointer.

    If you want to force shared_ptr to crash you whenever -> is used on a null pointer, um, I don't believe there's anything standard. Your compiler may have a debugging option you can turn on, though -- for instance, if I compile your program with gcc 4.5 and -D_GLIBCXX_DEBUG, I get

    $ ./a.out 
    /usr/include/c++/4.5/bits/shared_ptr_base.h:710: 
    _Tp* std::__shared_ptr<_Tp, _Lp>::operator->() const 
    [with _Tp = A, __gnu_cxx::_Lock_policy _Lp = (__gnu_cxx::_Lock_policy)2u]: 
    Assertion '_M_ptr != 0' failed.
    Aborted
    

    Can't help you with MSVC, sorry.