std::shared_ptr vs std::weak_ptr in terms of application [duplicate] - c++

I started studying smart pointers of C++11 and I don't see any useful use of std::weak_ptr. Can someone tell me when std::weak_ptr is useful/necessary?

std::weak_ptr is a very good way to solve the dangling pointer problem. By just using raw pointers it is impossible to know if the referenced data has been deallocated or not. Instead, by letting a std::shared_ptr manage the data, and supplying std::weak_ptr to users of the data, the users can check validity of the data by calling expired() or lock().
You could not do this with std::shared_ptr alone, because all std::shared_ptr instances share the ownership of the data which is not removed before all instances of std::shared_ptr are removed. Here is an example of how to check for dangling pointer using lock():
#include <iostream>
#include <memory>
int main()
{
// OLD, problem with dangling pointer
// PROBLEM: ref will point to undefined data!
int* ptr = new int(10);
int* ref = ptr;
delete ptr;
// NEW
// SOLUTION: check expired() or lock() to determine if pointer is valid
// empty definition
std::shared_ptr<int> sptr;
// takes ownership of pointer
sptr.reset(new int);
*sptr = 10;
// get pointer to data without taking ownership
std::weak_ptr<int> weak1 = sptr;
// deletes managed object, acquires new pointer
sptr.reset(new int);
*sptr = 5;
// get pointer to new data without taking ownership
std::weak_ptr<int> weak2 = sptr;
// weak1 is expired!
if(auto tmp = weak1.lock())
std::cout << "weak1 value is " << *tmp << '\n';
else
std::cout << "weak1 is expired\n";
// weak2 points to new data (5)
if(auto tmp = weak2.lock())
std::cout << "weak2 value is " << *tmp << '\n';
else
std::cout << "weak2 is expired\n";
}
Output
weak1 is expired
weak2 value is 5

A good example would be a cache.
For recently accessed objects, you want to keep them in memory, so you hold a strong pointer to them. Periodically, you scan the cache and decide which objects have not been accessed recently. You don't need to keep those in memory, so you get rid of the strong pointer.
But what if that object is in use and some other code holds a strong pointer to it? If the cache gets rid of its only pointer to the object, it can never find it again. So the cache keeps a weak pointer to objects that it needs to find if they happen to stay in memory.
This is exactly what a weak pointer does -- it allows you to locate an object if it's still around, but doesn't keep it around if nothing else needs it.

Another answer, hopefully simpler. (for fellow googlers)
Suppose you have Team and Member objects.
Obviously it's a relationship : the Team object will have pointers to its Members. And it's likely that the members will also have a back pointer to their Team object.
Then you have a dependency cycle. If you use shared_ptr, objects will no longer be automatically freed when you abandon reference on them, because they reference each other in a cyclic way. This is a memory leak.
You break this by using weak_ptr. The "owner" typically use shared_ptr and the "owned" use a weak_ptr to its parent, and convert it temporarily to shared_ptr when it needs access to its parent.
Store a weak ptr :
weak_ptr<Parent> parentWeakPtr_ = parentSharedPtr; // automatic conversion to weak from shared
then use it when needed
shared_ptr<Parent> tempParentSharedPtr = parentWeakPtr_.lock(); // on the stack, from the weak ptr
if( !tempParentSharedPtr ) {
// yes, it may fail if the parent was freed since we stored weak_ptr
} else {
// do stuff
}
// tempParentSharedPtr is released when it goes out of scope

Here's one example, given to me by #jleahy: Suppose you have a collection of tasks, executed asynchronously, and managed by an std::shared_ptr<Task>. You may want to do something with those tasks periodically, so a timer event may traverse a std::vector<std::weak_ptr<Task>> and give the tasks something to do. However, simultaneously a task may have concurrently decided that it is no longer needed and die. The timer can thus check whether the task is still alive by making a shared pointer from the weak pointer and using that shared pointer, provided it isn't null.

When using pointers it's important to understand the different types of pointers available and when it makes sense to use each one. There are four types of pointers in two categories as follows:
Raw pointers:
Raw Pointer [ i.e. SomeClass* ptrToSomeClass = new SomeClass(); ]
Smart pointers:
Unique Pointers [ i.e. std::unique_ptr<SomeClass> uniquePtrToSomeClass ( new SomeClass() ); ]
Shared Pointers [ i.e. std::shared_ptr<SomeClass> sharedPtrToSomeClass ( new SomeClass() ); ]
Weak Pointers [ i.e. std::weak_ptr<SomeClass> weakPtrToSomeWeakOrSharedPtr ( weakOrSharedPtr ); ]
Raw pointers (sometimes referred to as "legacy pointers", or "C pointers") provide 'bare-bones' pointer behavior and are a common source of bugs and memory leaks. Raw pointers provide no means for keeping track of ownership of the resource and developers must call 'delete' manually to ensure they are not creating a memory leak. This becomes difficult if the resource is shared as it can be challenging to know whether any objects are still pointing to the resource. For these reasons, raw pointers should generally be avoided and only used in performance-critical sections of the code with limited scope.
Unique pointers are a basic smart pointer that 'owns' the underlying raw pointer to the resource and is responsible for calling delete and freeing the allocated memory once the object that 'owns' the unique pointer goes out of scope. The name 'unique' refers to the fact that only one object may 'own' the unique pointer at a given point in time. Ownership may be transferred to another object via the move command, but a unique pointer can never be copied or shared. For these reasons, unique pointers are a good alternative to raw pointers in the case that only one object needs the pointer at a given time, and this alleviates the developer from the need to free memory at the end of the owning object's lifecycle.
Shared pointers are another type of smart pointer that are similar to unique pointers, but allow for many objects to have ownership over the shared pointer. Like unique pointer, shared pointers are responsible for freeing the allocated memory once all objects are done pointing to the resource. It accomplishes this with a technique called reference counting. Each time a new object takes ownership of the shared pointer the reference count is incremented by one. Similarly, when an object goes out of scope or stops pointing to the resource, the reference count is decremented by one. When the reference count reaches zero, the allocated memory is freed. For these reasons, shared pointers are a very powerful type of smart pointer that should be used anytime multiple objects need to point to the same resource.
Finally, weak pointers are another type of smart pointer that, rather than pointing to a resource directly, they point to another pointer (weak or shared). Weak pointers can't access an object directly, but they can tell whether the object still exists or if it has expired. A weak pointer can be temporarily converted to a shared pointer to access the pointed-to object (provided it still exists). To illustrate, consider the following example:
You are busy and have overlapping meetings: Meeting A and Meeting B
You decide to go to Meeting A and your co-worker goes to Meeting B
You tell your co-worker that if Meeting B is still going after Meeting A ends, you will join
The following two scenarios could play out:
Meeting A ends and Meeting B is still going, so you join
Meeting A ends and Meeting B has also ended, so you can't join
In the example, you have a weak pointer to Meeting B. You are not an "owner" in Meeting B so it can end without you, and you do not know whether it ended or not unless you check. If it hasn't ended, you can join and participate, otherwise, you cannot. This is different than having a shared pointer to Meeting B because you would then be an "owner" in both Meeting A and Meeting B (participating in both at the same time).
The example illustrates how a weak pointer works and is useful when an object needs to be an outside observer, but does not want the responsibility of sharing ownership. This is particularly useful in the scenario that two objects need to point to each other (a.k.a. a circular reference). With shared pointers, neither object can be released because they are still 'strongly' pointed to by the other object. When one of the pointers is a weak pointer, the object holding the weak pointer can still access the other object when needed, provided it still exists.

They are useful with Boost.Asio when you are not guaranteed that a target object still exists when an asynchronous handler is invoked. The trick is to bind a weak_ptr into the asynchonous handler object, using std::bind or lambda captures.
void MyClass::startTimer()
{
std::weak_ptr<MyClass> weak = shared_from_this();
timer_.async_wait( [weak](const boost::system::error_code& ec)
{
auto self = weak.lock();
if (self)
{
self->handleTimeout();
}
else
{
std::cout << "Target object no longer exists!\n";
}
} );
}
This is a variant of the self = shared_from_this() idiom often seen in Boost.Asio examples, where a pending asynchronous handler will not prolong the lifetime of the target object, yet is still safe if the target object is deleted.

shared_ptr : holds the real object.
weak_ptr : uses lock to connect to the real owner or returns a NULL shared_ptr otherwise.
Roughly speaking, weak_ptr role is similar to the role of housing agency. Without agents, to get a house on rent we may have to check random houses in the city. The agents make sure that we visit only those houses which are still accessible and available for rent.

weak_ptr is also good to check the correct deletion of an object - especially in unit tests. Typical use case might look like this:
std::weak_ptr<X> weak_x{ shared_x };
shared_x.reset();
BOOST_CHECK(weak_x.lock());
... //do something that should remove all other copies of shared_x and hence destroy x
BOOST_CHECK(!weak_x.lock());

Apart from the other already mentioned valid use cases std::weak_ptr is an awesome tool in a multithreaded environment, because
It doesn't own the object and so can't hinder deletion in a different thread
std::shared_ptr in conjunction with std::weak_ptr is safe against dangling pointers - in opposite to std::unique_ptr in conjunction with raw pointers
std::weak_ptr::lock() is an atomic operation (see also About thread-safety of weak_ptr)
Consider a task to load all images of a directory (~10.000) simultaneously into memory (e.g. as a thumbnail cache). Obviously the best way to do this is a control thread, which handles and manages the images, and multiple worker threads, which load the images. Now this is an easy task. Here's a very simplified implementation (join() etc is omitted, the threads would have to be handled differently in a real implementation etc)
// a simplified class to hold the thumbnail and data
struct ImageData {
std::string path;
std::unique_ptr<YourFavoriteImageLibData> image;
};
// a simplified reader fn
void read( std::vector<std::shared_ptr<ImageData>> imagesToLoad ) {
for( auto& imageData : imagesToLoad )
imageData->image = YourFavoriteImageLib::load( imageData->path );
}
// a simplified manager
class Manager {
std::vector<std::shared_ptr<ImageData>> m_imageDatas;
std::vector<std::unique_ptr<std::thread>> m_threads;
public:
void load( const std::string& folderPath ) {
std::vector<std::string> imagePaths = readFolder( folderPath );
m_imageDatas = createImageDatas( imagePaths );
const unsigned numThreads = std::thread::hardware_concurrency();
std::vector<std::vector<std::shared_ptr<ImageData>>> splitDatas =
splitImageDatas( m_imageDatas, numThreads );
for( auto& dataRangeToLoad : splitDatas )
m_threads.push_back( std::make_unique<std::thread>(read, dataRangeToLoad) );
}
};
But it becomes much more complicated, if you want to interrupt the loading of the images, e.g. because the user has chosen a different directory. Or even if you want to destroy the manager.
You'd need thread communication and have to stop all loader threads, before you may change your m_imageDatas field. Otherwise the loaders would carry on loading until all images are done - even if they are already obsolete. In the simplified example, that wouldn't be too hard, but in a real environment things can be much more complicated.
The threads would probably be part of a thread pool used by multiple managers, of which some are being stopped, and some aren't etc. The simple parameter imagesToLoad would be a locked queue, into which those managers push their image requests from different control threads with the readers popping the requests - in an arbitrary order - at the other end. And so the communication becomes difficult, slow and error-prone. A very elegant way to avoid any additional communication in such cases is to use std::shared_ptr in conjunction with std::weak_ptr.
// a simplified reader fn
void read( std::vector<std::weak_ptr<ImageData>> imagesToLoad ) {
for( auto& imageDataWeak : imagesToLoad ) {
std::shared_ptr<ImageData> imageData = imageDataWeak.lock();
if( !imageData )
continue;
imageData->image = YourFavoriteImageLib::load( imageData->path );
}
}
// a simplified manager
class Manager {
std::vector<std::shared_ptr<ImageData>> m_imageDatas;
std::vector<std::unique_ptr<std::thread>> m_threads;
public:
void load( const std::string& folderPath ) {
std::vector<std::string> imagePaths = readFolder( folderPath );
m_imageDatas = createImageDatas( imagePaths );
const unsigned numThreads = std::thread::hardware_concurrency();
std::vector<std::vector<std::weak_ptr<ImageData>>> splitDatas =
splitImageDatasToWeak( m_imageDatas, numThreads );
for( auto& dataRangeToLoad : splitDatas )
m_threads.push_back( std::make_unique<std::thread>(read, dataRangeToLoad) );
}
};
This implementation is nearly as easy as the first one, doesn't need any additional thread communication, and could be part of a thread pool/queue in a real implementation. Since the expired images are skipped, and non-expired images are processed, the threads never would have to be stopped during normal operation.
You could always safely change the path or destroy your managers, since the reader fn checks, if the owning pointer isn't expired.

I see a lot of interesting answers that explain reference counting etc., but I am missing a simple example that demonstrates how you prevent memory leak using weak_ptr. In first example I use shared_ptr in cyclically referenced classes. When the classes go out of scope they are NOT destroyed.
#include<iostream>
#include<memory>
using namespace std;
class B;
class A
{
public:
shared_ptr<B>bptr;
A() {
cout << "A created" << endl;
}
~A() {
cout << "A destroyed" << endl;
}
};
class B
{
public:
shared_ptr<A>aptr;
B() {
cout << "B created" << endl;
}
~B() {
cout << "B destroyed" << endl;
}
};
int main()
{
{
shared_ptr<A> a = make_shared<A>();
shared_ptr<B> b = make_shared<B>();
a->bptr = b;
b->aptr = a;
}
// put breakpoint here
}
If you run the code snippet you will see as classes are created, but not destroyed:
A created
B created
Now we change shared_ptr's to weak_ptr:
class B;
class A
{
public:
weak_ptr<B>bptr;
A() {
cout << "A created" << endl;
}
~A() {
cout << "A destroyed" << endl;
}
};
class B
{
public:
weak_ptr<A>aptr;
B() {
cout << "B created" << endl;
}
~B() {
cout << "B destroyed" << endl;
}
};
int main()
{
{
shared_ptr<A> a = make_shared<A>();
shared_ptr<B> b = make_shared<B>();
a->bptr = b;
b->aptr = a;
}
// put breakpoint here
}
This time, when using weak_ptr we see proper class destruction:
A created
B created
B destroyed
A destroyed

I see std::weak_ptr<T> as a handle to a std::shared_ptr<T>: It allows me
to get the std::shared_ptr<T> if it still exists, but it will not extend its
lifetime. There are several scenarios when such point of view is useful:
// Some sort of image; very expensive to create.
std::shared_ptr< Texture > texture;
// A Widget should be able to quickly get a handle to a Texture. On the
// other hand, I don't want to keep Textures around just because a widget
// may need it.
struct Widget {
std::weak_ptr< Texture > texture_handle;
void render() {
if (auto texture = texture_handle.get(); texture) {
// do stuff with texture. Warning: `texture`
// is now extending the lifetime because it
// is a std::shared_ptr< Texture >.
} else {
// gracefully degrade; there's no texture.
}
}
};
Another important scenario is to break cycles in data structures.
// Asking for trouble because a node owns the next node, and the next node owns
// the previous node: memory leak; no destructors automatically called.
struct Node {
std::shared_ptr< Node > next;
std::shared_ptr< Node > prev;
};
// Asking for trouble because a parent owns its children and children own their
// parents: memory leak; no destructors automatically called.
struct Node {
std::shared_ptr< Node > parent;
std::shared_ptr< Node > left_child;
std::shared_ptr< Node > right_child;
};
// Better: break dependencies using a std::weak_ptr (but not best way to do it;
// see Herb Sutter's talk).
struct Node {
std::shared_ptr< Node > next;
std::weak_ptr< Node > prev;
};
// Better: break dependencies using a std::weak_ptr (but not best way to do it;
// see Herb Sutter's talk).
struct Node {
std::weak_ptr< Node > parent;
std::shared_ptr< Node > left_child;
std::shared_ptr< Node > right_child;
};
Herb Sutter has an excellent talk that explains the best use of language
features (in this case smart pointers) to ensure Leak Freedom by Default
(meaning: everything clicks in place by construction; you can hardly screw it
up). It is a must watch.

http://en.cppreference.com/w/cpp/memory/weak_ptr
std::weak_ptr is a smart pointer that holds a non-owning ("weak") reference to an object that is managed by std::shared_ptr. It must be converted to std::shared_ptr in order to access the referenced object.
std::weak_ptr models temporary ownership: when an object needs to be accessed only if it exists, and it may be deleted at any time by someone else, std::weak_ptr is used to track the object, and it is converted to std::shared_ptr to assume temporary ownership. If the original std::shared_ptr is destroyed at this time, the object's lifetime is extended until the temporary std::shared_ptr is destroyed as well.
In addition, std::weak_ptr is used to break circular references of std::shared_ptr.

There is a drawback of shared pointer:
shared_pointer can't handle the parent-child cycle dependency. Means if the parent class uses the object of child class using a shared pointer, in the same file if child class uses the object of the parent class. The shared pointer will be failed to destruct all objects, even shared pointer is not at all calling the destructor in cycle dependency scenario. basically shared pointer doesn't support the reference count mechanism.
This drawback we can overcome using weak_pointer.

When we does not want to own the object:
Ex:
class A
{
shared_ptr<int> sPtr1;
weak_ptr<int> wPtr1;
}
In the above class wPtr1 does not own the resource pointed by wPtr1. If the resource is got deleted then wPtr1 is expired.
To avoid circular dependency:
shard_ptr<A> <----| shared_ptr<B> <------
^ | ^ |
| | | |
| | | |
| | | |
| | | |
class A | class B |
| | | |
| ------------ |
| |
-------------------------------------
Now if we make the shared_ptr of the class B and A, the use_count of the both pointer is two.
When the shared_ptr goes out od scope the count still remains 1 and hence the A and B object does not gets deleted.
class B;
class A
{
shared_ptr<B> sP1; // use weak_ptr instead to avoid CD
public:
A() { cout << "A()" << endl; }
~A() { cout << "~A()" << endl; }
void setShared(shared_ptr<B>& p)
{
sP1 = p;
}
};
class B
{
shared_ptr<A> sP1;
public:
B() { cout << "B()" << endl; }
~B() { cout << "~B()" << endl; }
void setShared(shared_ptr<A>& p)
{
sP1 = p;
}
};
int main()
{
shared_ptr<A> aPtr(new A);
shared_ptr<B> bPtr(new B);
aPtr->setShared(bPtr);
bPtr->setShared(aPtr);
return 0;
}
output:
A()
B()
As we can see from the output that A and B pointer are never deleted and hence memory leak.
To avoid such issue just use weak_ptr in class A instead of shared_ptr which makes more sense.

Inspired by #offirmo's response I wrote this code and then ran the visual studio diagnostic tool:
#include <iostream>
#include <vector>
#include <memory>
using namespace std;
struct Member;
struct Team;
struct Member {
int x = 0;
Member(int xArg) {
x = xArg;
}
shared_ptr<Team> teamPointer;
};
struct Team {
vector<shared_ptr<Member>> members;
};
void foo() {
auto t1 = make_shared<Team>();
for (int i = 0; i < 1000000; i++) {
t1->members.push_back(make_shared<Member>(i));
t1->members.back()->teamPointer = t1;
}
}
int main() {
foo();
while (1);
return 0;
}
When the member pointer to the team is shared_ptr teamPointer the memory is not free after foo() is done, i.e. it stays at around 150 MB.
But if it's changed to weak_ptr teamPointer in the diagnostic tool you'll see a peak and then memory usage returns to about 2MB.

Related

C++ Storing a shared object but not taking ownership

I have a situation where I have a piece of hardware and it really only makes sense for a single connection to be open on that hardware at the same time, so I really only want to refer to one object no matter where it's passed. So it may look something like:
class Hardware {
public:
void Open(); //this will create and launch a connection monitor in the background
void Close();
std::string SendPing();
std::string AskForSomeOtherData();
bool isConnected();
bool setConnected(bool connState);
private:
bool connected_;
int hndl_;
}
I then have another class monitoring the connection in the background so my UI can be notified if a connection is lost.
class ConnectionMonitor{
ConnectionMonitor(Hardware& hw);
void Run(); //launches a background thread to send "pings" to the device to make sure it's there. Will update Hardware.connected_
Hardware hw_; //or Hardware* hw_, or shared_ptr<Hardware> hw_, or Hardware& hw_;
}
When the connection monitor notices a connection is lost, it needs to update the connected boolean of the hardware object passed in directly, because my other threads using the object will also want to know it's been disconnected. But I don't know if updating the private data of the object indicates ownership of the object itself?
I don't believe so, since the lifetime of the object shouldn't be effected. There are all these different ways to pass an object shared between two classes, but I don't know what the problem domain calls for when I need to store it in class private data. Requiring a shared pointer to be passed in is one option. But I am not really indicating any ownership of the object being taken I don't think? A reference seems to be more fitting possibly, but then I end up with needing Hardware& hw; in my ConnectionMonitor private data so I keep a reference to the Hardware object. Then I read stuff that says "Reference in private data bad."
Also, if the caller is storing the hardware object as a shared_ptr, I believe I would have to do something like the following to pass it into my ConnectionMonitor:
ConnectionMonitor(*hardware);
but is this ok for a shared pointer, to dereference it, pass the object to a constructor, and then have the consuming class store another pointer to the same object that the shared pointer owns?
ConnectionMonitor(Hardware& hw){
Hardware* = hw; //not 100% sure if this syntax is correct, still learning. Most importantly here I'd be taking the hw object being referenced and pointing at it internally, rather than creating a copy
}
It seems now I am now creating a pointer to an object that the shared pointer already owns.
There are a lot of questions embedded above in what amounts to be a brain dump on my thought process, so I will try to summarize. When two threads need access to the same resource, and that resource needs to be updated from either thread, is this a case for a shared pointer? If one of the classes is not taking ownership, what is the best way to store that shared object in private data?
but is this ok for a shared pointer, to dereference it, pass the object to a constructor, and then have the consuming class store another pointer to the same object that the shared pointer owns?
Yes raw pointers are fine when the are non-owning. You can use std::shared_ptr::get to retrieve the stored raw pointer. However, when you store the raw pointer you need to consider the lifetime of the object. For example this is fine:
#include <memory>
#include <iostream>
struct bar {
std::shared_ptr<int> owning_ptr;
bar() : owning_ptr(std::make_shared<int>(42)) {}
~bar() { std::cout << "bar destructor\n"; }
};
struct foo {
int* non_owning_ptr;
~foo() { std::cout << "foo destructor\n"; }
};
struct foobar {
bar b;
foo f;
foobar() : b(),f{b.owning_ptr.get()} {}
};
int main() {
foobar fb;
}
b gets initialized first and f can use a pointer to the int managed by owning_ptr. Because f gets destroyed first, there is no danger of f using non_owning_ptr after owning_ptr already deleted the int.
However, only in certain circumstances you can be certain that the raw pointer can only be used as long as the object managed by a smart pointer is alive. As mentioned in a comment, the non-owning counter part to std::shared_ptr is std::weak_ptr. It does not increment the reference count, hence does not prevent the managed object to be deleted when all std::shared_ptrs to the object are gone.
#include <memory>
#include <iostream>
struct moo {
std::weak_ptr<int> weak;
void do_something() {
std::shared_ptr<int> ptr = weak.lock();
if (ptr) { std::cout << "the int is still alive: " << *ptr << "\n"; }
else { std::cout << "the int is already gone\n"; }
}
};
int main() {
moo m;
{
std::shared_ptr<int> soon_gone = std::make_shared<int>(42);
m.weak = soon_gone;
m.do_something();
}
m.do_something();
}
Output is:
the int is still alive: 42
the int is already gone
As already mentioned the std::weak_ptr does not keep the object alive. Though, it has a lock method that locks the object from being destroyed as long as the returned std::shared_ptr is alive. When lock is called on the weak_ptr when the object is already gone, also the returned shared pointer is empty.
When two threads need access to the same resource, and that resource needs to be updated from either thread, is this a case for a shared pointer?
Yes and no. The ref counting of std::shared_ptr is thread safe. Though using a shared pointer does not automagically make the pointee thread safe. You need some synchronization mechanism to avoid data races.

shared_ptr and threads issue

The code I'm currently working on had it's own RefPtr implementation which was failing at random.
I suspect that this could be a classic data race. RefPtr has a pointer to original object that inherits from the RefCounted class. This class contains a reference counter (m_refCount) that is not atomic and an application was crashing inside some threadwork accessing object through RefPtr stuff. Just like the object under RefPtr got destroyed. Quite impossible.
The object instance that is held by RefPtr is also held by two other objects that do not modify it (or its contents) and I'm 100% sure that they have shared ownership of it (so m_refCount should never go below 2)
I did try to replace the pointer with std::shared_ptr, but the crash is still there.
The distilled code representing this issue:
class SharedObjectA
{
public:
int a;
}
class Owner
{
public:
shared_ptr<SharedObjectA> objectA;
}
class SecondOwner
{
shared_ptr<SharedObjectA> objcectA;
public:
shared_ptr<SharedObjectA> GetSharedObject() { return objectA;}
void SetSharedObject(shared_ptr<SharedObjectA> objA) { objectA = objA;}
}
void doSomethingThatTakesTime(SecondOwnerA* owner)
{
sleep(1000+rand()%1000);
shared_ptr<SharedObjectA> anObject = owner->GetSharedObject();
int value = anObject.a;
std::cout << " says: " << value;
}
int main()
{
Owner ownerA;
ownerA.objectA.reset(new SharedObjectA());
SecondOwner secondOwner;
secondOwner.SetSharedObject(ownerA.objectA);
//objectA instance
while(true)
{
for(int i=0;i<4;i++)
{
std::thread tr(doSomethingThatTakesTime,secondOwner);
}
sleep(4*1000);
}
}
What's happening is up to 4 threads access SharedObject using GetSharedObject and do something with it.
However, after giving it some time - the use_count() of shared_ptr will go down below 2 (it should not) and eventually below 1 so the object(objectA) will get destroyed.
Edit
Obviously there is no synchronization in this code. However i don't see how this could be related to the fact the use_count() getting below 2. the shared_ptr is guaranteed to be thread safe for the sake of reference counting, isn't it?
You don't have any kind of synchronization on access to the shared object. shared_ptr does not do any synchronization in access to the pointed-to object, it just ensures that the memory pointed to gets released after all references to it are destroyed.
You also need to join() your threads at some point.

Is there such thing as a weak_ptr that can't be locked (promoted to shared_ptr)? If not, why?

Maybe this question has been asked before, but I've never found a satisfactory answer. Also, for the purposes of simplicity assume I'm talking about a single-threaded application.
So, what I've heard a number of times is that if you have an object that is non-owned and whose lifetime is guaranteed, you should reference it with a raw pointer. The object's owner would use a unique_ptr, and hand out raw pointers as necessary.
But what if the object is non-owned, and the lifetime is not guaranteed? Then you can use a weak_ptr, yes. But then anyone who is handed a weak_ptr could be naughty and keep it locked, such that the object's owner can't cause the object to be destroyed. Sometimes this may not be a problem, but sometimes it is. For example, when the owned object represents some system resource which must be relinquished at a certain time.
You may say "well, then you should just make sure no one keeps the weak_ptr locked!" But that is just not ideal (in my opinion) from an OO design standpoint, as it creates a dependency between the "owner" object and any object that gets a weak_ptr from it. You might as well make the argument "you don't need to return const references; you should just make sure no one modifies the reference."
With Qt, you have the QPointer, which is basically what I'm looking for. It checks that the object hasn't been destroyed, but it can't prevent the object from being destroyed. I realize this isn't thread-safe, but again, I'm talking about the context of a single thread.
So why isn't there something similar for C++11? I'm sure I could make a wrapper around weak_ptr that accomplishes what I'm after. But I wonder if I'm going about this all wrong.
No. And it doesn't exist is because it's unsafe even for a single thread. Consider:
void some_function (super_weak_ptr foo)
{
foo->some_function();
}
What happens if some_function (through an indirect path) causes the object to be destroyed? And before you say that can never happen, yes it can. For example:
void got_some_data (some_type whatObject, some_other_type whatData)
{
super_weak_ptr object = findObject (whatObject);
if (object)
object->youGotMail (whatData);
}
Now, suppose the youGotMail function realizes that the object now got the last bit of data it needs and its job is complete, it might destroy that object, and now we're running a function on an object that no longer exists.
If you want a raw pointer, you know where to find one. It doesn't make much sense to create a "smart" pointer that's no safer than a raw pointer.
So if you're not managing the lifetime of an object, you need the ability to lock that object before you can do anything to that object.
You can do this with pure Standard C++ using shared_ptr<unique_ptr<T>>.
Observers received only a shared_ptr<const unique_ptr<T>>, allowing them to look but not touch. The owner, having a non-const smart pointer, can at any time call reset() on the unique_ptr to destroy the instance. At that time all the observers can also see that the unique_ptr has become empty.
Obvious threading and re-entrance caveats apply (you need to check the unique_ptr for having a valid pointer again after each callback you invoke, etc).
And if there should be multiple owners, it's a bit more work. You will need one shared_ptr<T*>, giving observers a shared_ptr<T* const>. And a separate shared_ptr<T> to manage the object lifetime. The shared_ptr<T*> will need to be manually filled with nullptr (The T*, not the shared_ptr) in the object's destructor.
There is no such thing, alas.
In 2009 I toyed with / explored such a smart pointer type that I called ZPtr, as I recall as a cleanup effort of some earlier code in that direction, in the context of supporting better file abstraction error handling than the silence treatment of the standard library's iostreams. The (earlier) idea was to not have any zombie objects around, by self-destroying when no further meaningful operations were possible, and this required access via a smart pointer that could detect the existence or not of the referent. Evidently it was not such a good idea at the time, because the article I sent to DDJ about it was rejected … by the silence treatment.
I think now that we have argument forwarding support in the language, the time for such a pointer may have come. It would be even better with possible overloading of the . operator. But the functionality will anyway have to be chosen very carefully.
The std::weak_ptr isn't really "locked", in spite of naming. It's just used to obtain a std::shared_ptr, if possible. And a std::shared_ptr readily supplies you with a raw pointer.
So you can choose to hand out not std::weak_ptr directly, but a wrapper that only provides a temporary raw pointer.
It will not be very thread safe though, and unlike a ZPtr it will not give the client code any idea of why the referent doesn't exist any more (when it doesn't). But it just may be all that you need. Let me get some coffee & a bite to eat, then I'll cook up an example.
Example:
#include <memory>
namespace cppx {
using std::shared_ptr;
using std::weak_ptr;
template< class Type >
class Poor_ptr
{
private:
struct Null {};
weak_ptr<Type> weak_p_;
public:
explicit operator bool() const { return not is_null(); }
friend
auto operator==( const Poor_ptr& p, Poor_ptr::Null* )
-> bool
{ return p.is_null(); }
friend
auto operator==( Poor_ptr::Null*, const Poor_ptr& p )
-> bool
{ return p.is_null(); }
friend
auto operator!=( const Poor_ptr& p, Poor_ptr::Null* )
-> bool
{ return not p.is_null(); }
friend
auto operator!=( Poor_ptr::Null*, const Poor_ptr& p )
-> bool
{ return not p.is_null(); }
auto is_null() const
-> bool
{ return (ptr_or_null() == nullptr); }
auto ptr_or_null() const
-> Type*
{
try
{
return weak_p_.lock().get();
}
catch( ... )
{
return nullptr;
}
}
auto ptr() const
-> Type*
{ return weak_p_.lock().get(); }
Poor_ptr( shared_ptr< Type > p )
: weak_p_( p )
{}
};
} // namespace cppx
#include <iostream>
using namespace std;
auto main() -> int
{
cout << boolalpha;
auto p = make_shared<int>( 42 );
cppx::Poor_ptr<int> pp = p;
cout
<< "That " << pp.ptr_or_null() << " is null is "
<< (pp == 0) << ", not " << !!pp << ".\n";
p.reset();
cout
<< "That " << pp.ptr_or_null() << " is null is "
<< (pp == 0) << ", not " << !!pp << ".\n";
}
Oh, and to cover the problem that David Schwartz mentions, that of the object disappearing in mid-call of some function, you can just provide a member function that executes a functor such as std::function with a raw pointer as argument, where the referred to object is guaranteed kept alive during that call (namely by having a local std::shared_ptr).
Then the client code programmer can choose whether to rely on an assumption that called functions will not destroy the object, or use the safer callback mechanism.

"delete this" to an object that's allocated with std::shared_ptr?

I know that it's possible to say delete this in C++ whenever you allocated something with new, using traditional pointers. In fact, I also know that it's good practice IF you handle it carefully. Can I have an object say delete this if it's being held by an std::shared_ptr? And that ought to call the destructor, right? To give you an idea, I'm making a game where a ship can shoot missiles, and I'd like to have the missiles delete themselves.
No, it's not safe, the lifetime of the object is determined by holders of shared_ptr, so the object itself cannot decide whether it wants to die or not. If you do that, you'll get double
delete when last shared_ptr dies. The only solution I can offer is "rethink your design" (you probably don't need shared_ptr in the first place, and missiles probably could be values or pooled objects).
For a missile to delete itself it must own itself, or at the very least, share ownership of itself with others. Since you say that there is a shared_ptr to the missile, I am assuming that you already have multiple objects sharing ownership of the missile.
It is possible for the missile to hold a shared_ptr to itself, and thus share in the ownership of itself. However this will always create a cyclic ownership pattern: For as long as the missile's shared_ptr data member refers to itself, the reference count can never drop to zero, and thus the missile is leaked.
You could have an external object or event tell the missile to delete itself but then I'm not sure what the point is. In order to tell the missile to delete itself, that communication should take place via a shared_ptr, and then the delete isn't really going to happen until that shared_ptr lets go of the missile.
Yes, it is possible. No, I don't think it is a good idea. It looks prone to memory leakage to me and doesn't actually add value. But for the curious, here is how you would do it:
#include <iostream>
#include <memory>
class missile
: public std::enable_shared_from_this<missile>
{
std::shared_ptr<missile> self_;
public:
missile()
{}
~missile() {std::cout << "~missile()\n";}
void set_yourself()
{
self_ = shared_from_this();
}
void delete_yourself()
{
if (self_)
self_.reset();
}
};
int main()
{
try
{
std::shared_ptr<missile> m = std::make_shared<missile>();
m->set_yourself();
std::weak_ptr<missile> wp = m;
std::cout << "before first reset()\n";
m.reset();
std::cout << "after first reset()\n";
// missile leaked here
m = wp.lock();
m->delete_yourself();
std::cout << "before second reset()\n";
m.reset(); // missile deleted here
std::cout << "after second reset()\n";
}
catch (const std::exception& e)
{
std::cout << e.what() << '\n';
}
}
I know I'm late to the show but I ran into wanting to do this myself just now and realized that it is "kind-of-possible" but you need to take care of a few things.
Howard's answer is on the right track but misses the mark as you shouldn't leave construction of the original shared_ptr to the client. This is what opens up the risk of memory leaks. Instead you should encapsulate the construction and only allow weak pointers.
Here is an example:
class Missile{
private:
Missile(...){ }; // No external construction allowed
Missile(const Missile&) = delete; // Copying not allowed
void operator = (const Missile&) = delete; // -||-
std::shared_ptr<Missile> m_self;
public:
template<typename... Args>
static MissilePtr makeMissile(Args... args){
auto that = std::make_shared<Misile>(args...);
that.m_self = that; // that holds a reference to itself (ref count = 2)
return that; // 'that' is destroyed and ref-count reaches 1.
}
void die(){
m_self.reset();
}
...
};
typedef std::weak_ptr<Missile> MissilePtr;
void useMissile(MissilePtr ptr){
auto missile = ptr.lock(); // Now ptr cannot be deleted until missile goes out of scope
missile->die(); // m_self looses the reference but 'missile' still holds a reference
missile->whatever(); // Completely valid. Will not invoke UB
} // Exiting the scope will make the data in missile be deleted.
Calling die() will result in semantically the same effect as delete this with the added benefit that all MissilePtr that are referring to the deleted object will be expired. Also if any of the MissilePtr are used for accessing this then the deletion will be delayed until the temporary std::shared_ptr used for the access is destroyed saving you life-time headaches.
However you must make sure that you always keep at least one MissilePtr around and at some point call die() otherwise you will end up with a memory leak. Just like you would with a normal pointer.
This question is quite old, but I had a similar issue (in this case a "listener" object that had to manage its own lifecycle while still being able to share weak pointers), and googling around did not provide a solution for me, so I am sharing the solution I found, assuming that:
The object manages it's own lifecycle, and hence will never share a
share_ptr, but a weak_ptr (if you need shared_ptr's a similar
solution + use_shared_from_this could do it).
It is a bad idea to break RAII, and hence we will not do it: what we
adress here is the issue of having a shared_ptr owned by an object
itself, as containing a member share_ptr leads to double call to
the object destruction and normally a crash (or at least undefined
behaviour), as the destructor is called twice (once at normal
object destruction and a second one when destroying the self
contained shared_ptr member).
Code:
#include <memory>
#include <stdio.h>
using std::shared_ptr;
using std::weak_ptr;
class A {
struct D {
bool deleted = false;
void operator()(A *p) {
printf("[deleter (%s)]\n", p, deleted ? "ignored":"deleted");
if(!deleted) delete p;
}
};
public: shared_ptr<A> $ptr = shared_ptr<A>(this, D());
public: ~A() {
std::get_deleter<A::D>($ptr)->deleted = true;
}
public: weak_ptr<A> ptr() { return $ptr; }
};
void test() {
A a;
printf("count: %d\n", a.ptr().lock().use_count());
printf("count: %d\n", a.ptr().use_count());
}
int main(int argc, char *argv[]) {
puts("+++ main");
test();
puts("--- main");
}
Output:
$ g++ -std=c++11 -o test test.cpp && ./test
+++ main
count: 2
count: 1
[deleter (ignored)]
--- main
The shared_ptr deleter should never get called for an object allocated in stack, so when it does at normal object destruction, it just bypasses the delete (we got to this point because the default object destructor was already called).

How to release pointer from boost::shared_ptr?

Can boost::shared_ptr release the stored pointer without deleting it?
I can see no release function exists in the documentation, also in the FAQ is explained why it does not provide release function, something like that the release can not be done on pointers that are not unique. My pointers are unique. How can I release my pointers ?
Or which boost smart pointer class to use that will allow me releasing of the pointer ?
I hope that you won't say use auto_ptr :)
Don't. Boost's FAQ entry:
Q. Why doesn't shared_ptr provide a release() function?
A. shared_ptr cannot give away ownership unless it's unique() because the other copy will still destroy the object.
Consider:
shared_ptr<int> a(new int);
shared_ptr<int> b(a); // a.use_count() == b.use_count() == 2
int * p = a.release();
// Who owns p now? b will still call delete on it in its destructor.
Furthermore, the pointer returned by release() would be difficult to deallocate reliably, as the source shared_ptr could have been created with a custom deleter.
So, this would be safe in case it's the only shared_ptr instance pointing to your object (when unique() returns true) and the object doesn't require a special deleter. I'd still question your design, if you used such a .release() function.
You could use fake deleter. Then pointers will not be deleted actually.
struct NullDeleter {template<typename T> void operator()(T*) {} };
// pp of type some_t defined somewhere
boost::shared_ptr<some_t> x(pp, NullDeleter() );
Kids, don't do this at home:
// set smarty to point to nothing
// returns old(smarty.get())
// caller is responsible for the returned pointer (careful)
template <typename T>
T* release (shared_ptr<T>& smarty) {
// sanity check:
assert (smarty.unique());
// only one owner (please don't play games with weak_ptr in another thread)
// would want to check the total count (shared+weak) here
// save the pointer:
T *raw = &*smarty;
// at this point smarty owns raw, can't return it
try {
// an exception here would be quite unpleasant
// now smash smarty:
new (&smarty) shared_ptr<T> ();
// REALLY: don't do it!
// the behaviour is not defined!
// in practice: at least a memory leak!
} catch (...) {
// there is no shared_ptr<T> in smarty zombie now
// can't fix it at this point:
// the only fix would be to retry, and it would probably throw again
// sorry, can't do anything
abort ();
}
// smarty is a fresh shared_ptr<T> that doesn't own raw
// at this point, nobody owns raw, can return it
return raw;
}
Now, is there a way to check if total count of owners for the ref count is > 1?
You need to use a deleter that you can request not to delete the underlying pointer.
See this answer (which has been marked as a duplicate of this question) for more information.
To let the pointer point to nothing again, you can call shared_ptr::reset().
However, this will delete the object pointed to when your pointer is the last reference to the object. This, however, is exactly the desired behaviour of the smart pointer in the first place.
If you just want a reference that does not hold the object alive, you can create a boost::weak_ptr (see boost documentation). A weak_ptr holds a reference to the object but does not add to the reference count, so the object gets deleted when only weak references exist.
The basis of sharing is trust. If some instance in your program needs to release the raw pointer, it is almost for sure that shared_ptr is the wrong type.
However, recently I wanted to do this too, as I needed to deallocate from a different process-heap. In the end I was taught that my older decision to use some std::shared_ptr was not thought-out.
I just routinely used this type for cleanup. But the pointer was just duplicated on a few places. Actually I needed a std::unique_ptr, which (suprise) has a release function.
Forgive them for they know not what they do.
This example works with boost::shared_ptr and msvs std::shared_ptr without memory leaks!
template <template <typename> class TSharedPtr, typename Type>
Type * release_shared(TSharedPtr<Type> & ptr)
{
//! this struct mimics the data of std:shared_ptr ( or boost::shared_ptr )
struct SharedVoidPtr
{
struct RefCounter
{
long _Uses;
long _Weaks;
};
void * ptr;
RefCounter * refC;
SharedVoidPtr()
{
ptr = refC = nullptr;
}
~SharedVoidPtr()
{
delete refC;
}
};
assert( ptr.unique() );
Type * t = ptr.get();
SharedVoidPtr sp; // create dummy shared_ptr
TSharedPtr<Type> * spPtr = (TSharedPtr<Type>*)( &sp );
spPtr->swap(ptr); // swap the contents
ptr.reset();
// now the xxx::shared_ptr is empy and
// SharedVoidPtr releases the raw poiter but deletes the underlying counter data
return t;
}
You can delete the shared pointer, which seems much the same to me. If pointers are always unique, then std::auto_ptr<> is a good choice. Bear in mind that unique pointers can't be used in STL containers, since operations on them do a lot of copying and temporary duplication.
I'm not entirely sure if your question is about achieving this, but if you want behaviour from a shared_ptr, where, if you release the value from one shared_ptr, all the other shared pointers to the same value become a nullptr, then you can put a unique_ptr in a shared_ptr to achieve that behaviour.
void print(std::string name, std::shared_ptr<std::unique_ptr<int>>& ptr)
{
if(ptr == nullptr || *ptr == nullptr)
{
std::cout << name << " points to nullptr" << std::endl;
}
else
{
std::cout << name << " points to value " << *(*ptr) << std::endl;
}
}
int main()
{
std::shared_ptr<std::unique_ptr<int>> original;
original = std::make_shared<std::unique_ptr<int>>(std::make_unique<int>(50));
std::shared_ptr<std::unique_ptr<int>> shared_original = original;
std::shared_ptr<std::unique_ptr<int>> thief = nullptr;
print(std::string("original"), original);
print(std::string("shared_original"), shared_original);
print(std::string("thief"), thief);
thief = std::make_shared<std::unique_ptr<int>>(original->release());
print(std::string("original"), original);
print(std::string("shared_original"), shared_original);
print(std::string("thief"), thief);
return 0;
}
Output:
original points to value 50
shared_original points to value 50
thief points to nullptr
original points to nullptr
shared_original points to nullptr
thief points to value 50
This behaviour allows you to share a resource (like an array), then later reuse that resource while invalidating all the shared references to this resource.
Here's a hack that might work. I wouldn't recommend it unless you're in a real bind.
template<typename T>
T * release_shared(std::shared_ptr<T> & shared)
{
static std::vector<std::shared_ptr<T> > graveyard;
graveyard.push_back(shared);
shared.reset();
return graveyard.back().get();
}
If your pointers are indeed unique do use std::unique_ptr or boost::scoped_ptr if the former is not available for your compiler. Otherwise consider combining the use of boost::shared_ptr with boost::weak_ptr. Check out the Boost documentation for details.
I am using Poco::HTTPRequestHandlerFactory which expects to return a raw HTTPRequestHandler*, the Poco framework deletes the handler once the request finishes.
Also using DI Sauce project to create the controllers, however the Injector returns shared_ptr which I cannot return directly, and returning handler.get() is no good either since the as soon as this function returns the shared_ptr goes out of scope and deletes then handler before its executed, so here is a reasonable (I think) reason to have a .release() method. I ended up creating a HTTPRequestHandlerWrapper class as follows :-
class HTTPRequestHandlerWrapper : public HTTPRequestHandler {
private:
sauce::shared_ptr<HTTPRequestHandler> _handler;
public:
HTTPRequestHandlerWrapper(sauce::shared_ptr<HTTPRequestHandler> handler) {
_handler = handler;
}
virtual void handleRequest(HTTPServerRequest& request, HTTPServerResponse& response) {
return _handler->handleRequest(request, response);
}
};
and then the factory would
HTTPRequestHandler* HttpHandlerFactory::createRequestHandler(const HTTPServerRequest& request) {
URI uri = URI(request.getURI());
auto path = uri.getPath();
auto method = request.getMethod();
sauce::shared_ptr<HTTPRequestHandler> handler = _injector->get<HTTPRequestHandler>(method + ":" + path);
return new HTTPRequestHandlerWrapper(handler);
}
which satisfied both Sauce and Poco and works nicely.
I needed to pass a pointer through async handlers and to keep the self-destruct behavior in case of failure but the final API expected a raw pointer, so I made this function to release from a single shared_ptr:
#include <memory>
template<typename T>
T * release(std::shared_ptr<T> & ptr)
{
struct { void operator()(T *) {} } NoDelete;
T * t = nullptr;
if (ptr.use_count() == 1)
{
t = ptr.get();
ptr.template reset<T>(nullptr, NoDelete);
}
return t;
}
If ptr.use_count() != 1 you shall get a nullptr instead.
Do note that, from cppreference (bold emphasis mine):
If use_count returns 1, there are no other owners. (The deprecated member function unique() is provided for this use case.) In multithreaded environment, this does not imply that the object is safe to modify because accesses to the managed object by former shared owners may not have completed, and because new shared owners may be introduced concurrently, such as by std::weak_ptr::lock.
Easy solution, increase the reference and then leak the shared_pointer.
boost::shared_ptr<MyType> shared_pointer_to_instance(new MyType());
new boost::shared_ptr<MyType>();
MyType * raw_pointer = shared_pointer_to_instance.get()
This will clearly cause a memory leak of both the shared_ptr and the MyType *