Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Making shared_ptr lose ownership of memory

I have a shared_ptr<MyProto> which I pass around. Eventually, in certain situations, I want pass the raw pointer to a function which then becomes the memory owner. In those cases the shared_ptr isn't responsible anymore for freeing the memory because the function I call took ownership. How do I get the shared_ptr to lose ownership?

The reason I want to have the shared_ptr lose ownership is that I want to use protocol buffer's AddAllocated functionality which takes an already allocated pointer and assumes ownership of it.

Example:

shared_ptr<MyProto> myProtoSharedPtr = // by this point this is the last reference to the heap allocated MyProto

// I want to add it to a collection and serialize the collection without copying
CollectionProto collectionProto;
collectionProto.mutable_my_proto().AddAllocated(myProtoSharedPtr.get()); // at this point collectionProto took ownership of the memory
std::string serialization = collectionProto.SerializeAsString();

// bad: myProtoSharedPtr.get() will be freed twice
like image 522
ytoledano Avatar asked Jun 13 '18 07:06

ytoledano


People also ask

What happens to the memory point of a shared_ptr when it dies?

And the memory pointed by the underlying pointer is deleted when:- The reference count becomes zero i.e. the last remaining shared_ptr object is destroyed. The last remaining shared_ptr object owning the pointer is assigned with some other pointer.

When does a shared_ptr release ownership of an object?

shared_ptr objects release ownership on the object they co-own as soon as they themselves are destroyed, or as soon as their value changes either by an assignment operation or by an explicit call to shared_ptr::reset.

What happens to a shared_ptr when it is deleted?

shared_ptr maintains a reference count as to how many shared_ptr objects own the same underlying pointer. And the memory pointed by the underlying pointer is deleted when:- The reference count becomes zero i.e. the last remaining shared_ptr object is destroyed.

What happens when a shared_ptr is constructed from an existing pointer?

If a shared_ptr is constructed from an existing pointer that is not shared_ptr the memory for the control structure has to be allocated. This Control block is destroyed and deallocated when the last weak ref goes away. A shared_ptr construction approach takes two steps


1 Answers

I think you can achieve what you want to do by sharing a unique pointer like this:

std::shared_ptr<std::unique_ptr<MyProto>> myProtoSharedUniquePtr;

Accessing it would be more indirect:

(*myProtoSharedUniquePtr)->do_stuff();

But you could take ownership like this:

CollectionProto collectionProto;
collectionProto.mutable_my_proto().AddAllocated(myProtoSharedUniquePtr->release()); // at this point collectionProto took ownership of the memory
std::string serialization = collectionProto.SerializeAsString();

However I would question why you are using a std::shared_ptr to begin with. The reason to use a std::shared_ptr is when you have no control over who will be last to access it, so each one gets to keep it alive until they are done. So it would be unusual to be able to guarantee all current std::shared_ptr instances are no longer in use.

Are you sure a std::unique_ptr would not be better for your needs?

like image 109
Galik Avatar answered Oct 05 '22 01:10

Galik