C++ Smart Pointers Scope and Resource Deleting

Viewed 65

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

3 Answers

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;
}

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

That is correct -- when create_resource() returns, the std::unique_ptr's destructor executes and deletes the resource object that it is holding.

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 ?

create_resource() is returning a dangling pointer -- that is, a pointer to the memory location where the resource object previously was located, but since the resource object was deleted, the pointer is no longer usable. Attempting to use dereference the dangling pointer will result in undefined behavior, including in some cases a segmentation fault.

The correct way to handle this situation is to have create_resource() return a std::unique_ptr<resource> instead of a resource *.

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

Your understanding is correct.

So how is the actual resource wrapped by the unique pointer still reachable

This assumption is wrong. It is not reachable anymore after the function returns.

The behaviour of the program is undefined. It calls a member function through an invalid pointer.

Related