Search code examples
c++shared-ptrsmart-pointersundefined-behavior

Is using shared_ptr after reset undefined behaviour?


I have this test program:

#include <iostream>
#include <memory>

class A {
public:
    A()
    {
        std::cout<<"A Constructor\n";
    }

    ~A(){
        std::cout<<"A Destructor\n";
    }

    void show()
    {
        std::cout<<"A::show()"<<'\n';
    }
};

int main()
{
    auto p1 = std::make_shared<A>();
    // Relinquishes ownership of p1 on the object
    // and pointer becomes NULL
    p1.reset();
    std::cout<<p1.get()<<'\n';
    std::cout<<p1.use_count()<<'\n';
    p1->show();
    return 0;
}

Which yields this output:

A Constructor
A Destructor
0
0
A::show()

I ran this via gdb and saw:

:
:
(gdb) s
A::show (this=0x0) at so.cpp:18
18              std::cout<<"A::show()"<<'\n';
(gdb) s
A::show()
:

The line A::show (this=0x0) at so.cpp:18 indicates that the underlying resource is null. I looked at another question but there the raw pointer was being used to invoke the member function. Is this case too similar to the one in that question since p1->show() too should be equivalent to something like p1.get()->show();. Is my understanding correct?


Solution

  • Just add a data member to the class and you can see visually undefined behavior.

    #include <iostream>
    #include <memory>
    
    class A {
    public:
        A()
        {
            std::cout<<"A Constructor\n";
        }
    
        ~A(){
            std::cout<<"A Destructor\n";
        }
    
        void show()
        {
            std::cout<<"A::show()"<<'\n';
            ++x;
        }
    
        int x = 0;
    };
    
    int main()
    {
        std::shared_ptr<A> p1(new A);
        // Relinquishes ownership of p1 on the object
        // and pointer becomes NULL
        p1.reset();
        std::cout<<p1.get()<<'\n';
        std::cout<<p1.use_count()<<'\n';
        p1->show();
        return 0;
    }
    

    For example at run-time an error like this

    Runtime error #stdin #stdout 0s 4280KB
    

    can be shown.

    That is the null-pointer was used to access the data member.