I am familiar with std::shared_ptr
and std::weak_ptr
and know how they work. However, I would like the std::shared_ptr
to emit a callback, like a boost signal. This would allow std::weak_ptr
, who still refer to the deleted object, to be cleaned up right in time.
Is there maybe already some smart pointer implementation, which will report the destruction?
Explanation
I think there might be a small design flaw in std::weak_ptr
s, that can lead to false memory leaks. By "false memory leak" I mean an object, that is still accessible by the program, but whose reason of existence is not valid anymore. The difference to a true memory leak is, that the true memory leak is completely unknown by the program, while the false leak is just a part that wasn't cleaned up properly.
Another description can be found at codingwisdom.com
Use Watchers
One of the problems with freeing an object is that you may have done so while other things are still pointing at it. This introduces dangling pointers and crashes! To combat the evil of dangling pointers, I like to use a basic "watcher" system. This is not unlike the weak reference discussed above. The implementation is like this:
Create a base class "Watchable" that you derive from on objects that should broadcast when they're being deleted. The Watchable object keeps track of other objects pointing at it. Create a "Watcher" smart pointer that, when assigned to, adds itself to the list of objects to be informed when its target goes away.
This basic technique will go a long way toward solving dangling pointer issues without sacrificing explicit control over when an object is to be destroyed.
Example
Let's say we implement the observer pattern using boost Boost Signals2. We have a class Observable
, that contains one or more signals and another class Observer
, that connects to Observable
's signals.
What would happen to Observable
's slots, when a observing Observer
is deleted? When we do nothing, then the connection would point to nowhere and we would probably receive a segmentation fault, when emitting the signal.
To deal with this issue, boost's slots also offer a method track(const weak_ptr<void>& tracked_object)
. That means, if I call track
and pass a weak_ptr
to Observer
, then the slot won't be called when the weak_ptr
expired. Instead, it will be deleted from the signal.
Where is the problem? Let's we delete an Observer
and never call a certain signal of Observable
ever again. In this case, the tracked connection will also never be deleted. Next time we emit the signal it will be cleaned up. But we don't emit it. So the connection just stays there and wastes resources.
A solution would be: when owning shared_ptr
should emit a signal when it is destroying it's object. This would allow other other objects to clean up right in time. Everything that has a weak_ptr
to the deleted object might register a callback and false memory leaks could be avoided.