Search code examples
c++functionscopec++14smart-pointers

C++ Smart Pointers Scope and Resource Deleting


I have the following simple code example:

#include <iostream>
#include <utility>
#include <memory>
using namespace std;

class resource
{
public:
   void print() { cout << "Class Still Alive" << endl; };
};

resource* create_resource()
{
   std::unique_ptr<resource> r = std::make_unique<resource>();
   return r.get();
}

void execute_resource(resource* r)
{
   r->print();
}

int main()
{
   resource* r = create_resource();
   execute_resource(r);
   return 0;
}

The unique ptr r created in create_resource goes out of scope at the end of the function. At least this is my understanding of scope.

So how is the actual resource wrapped by the unique pointer still reachable and does create a segmentation fault since its owning unique pointer should have gone out of scope and deleted this?

Compiling using: g++ test.cpp -std=c++14


Solution

  • Yes, your understanding is correct about the function scope. The std::unique_ptr<resource> will be destroyed after the create_resource function scope.


    So how is the actual resource wrapped by the unique pointer still reachable and does create a segmentation fault since its owning unique pointer should have gone out of scope and deleted this?

    Because of the reason mentioned above, what you receiving here in the main

    resource *r = create_resource();
    

    is a dangling pointer. Accessing it will cause the undefined bahviour and hence anything can happen. In your case, it is a segmentation fault.


    In order to fix the issue, you can return the std::unique_ptr<resource> itself from the create_resource function

    #include <iostream>
    #include <utility>
    #include <memory>
    
    class resource
    {
    public:
       void print() const // can be const
       { 
             std::cout << "Class Still Alive\n";
       };
    };
    
    std::unique_ptr<resource> create_resource()
    {
       return std::make_unique<resource>(); // return the std::unique_ptr<resource>
    }
    
    void execute_resource(resource* r)
    {
       r->print();
    }
    
    int main()
    {
       auto r = create_resource();
       execute_resource(r.get()); // pass the pointer to execute!
       return 0;
    }