note: this question is related to weak_ptr usage, but is not about wrapping weak_ptrs.
I am currently evaluating Swig and I have found an "inconvenience" in the usage of the wrappers by the client languages, that I have not found described online and for which I have no satisfactory solution.
In C++ if you have a complex graph of objects that are managed using shared_ptrs, you must take special care when the graph can have a cycle (i.e. if it is not a DAG) or else you will get memory leaks. By that I mean that if you must (cannot avoid) to have a cycle, it must contain at least one weak_ptr. This means that you will have to handle the cases where you cannot lock the weak_ptr, because the related shared_ptr has died. This management is something that one can expect C++ programmers to be used to deal with. Now let's look at what can happen for a user of the wrappers:
So let's take the following example:
object a, held by a shared_ptr, has a shared_ptr to b
object b, held by a shared_ptr, has a weak_ptr to a
The following could happen to a user of the wrapper:
A a
B b = a->GetB()
// here let's suppose that a gets out of scope, so it can be garbage collected
b->GetA() // fails if a has been garbage collected
The failure could be cleanly managed by propagating a C++ exception to the client code (throw if cannot lock the weak_ptr to create a shared_ptr). However this is not idiomatic to Python/C#/Java users: they do not except to have to manually keep some objects alive to access others.
I have a draft of a an alternative solution which involves creating a C++ "Co-Owner" of objects a and b that would be locked by the SWIG wrappers when any of a or b are accessed via the wrappers, thus keeping both a and b alive when any of them is accessed via the wrappers. The downsides are that this starts to look like I am implementing a proto-garbage-collection in C++, also this modifies the C++ implementation & API of objects a & b and finally the objects a & b will have to be notified by the wrappers that they are used via the wrappers (not something I think I can do without patching SWIG to add function calls in constructor and destructor of shadow objects ??).
Have I missed anything ? Is there another solution to this problem ?
Publicly available weak pointers
If weak ownership is actually part of the interface, it is possible to bind extra types manually that exhibit the behavior of weak pointers. In this example they create a type FooWeakPtr providing the relevant interface. But as you can see, this is not taking advantage of the language-specific classes in every language.
Internal weak pointers
If the weak pointers are not part of the interface, then SWIG-generated bindings should not care about them, and treat the bound objects as shared pointers (at least in Python and Java). Therefore, for as long as your objects are available from the other language, you must make sure they all stay alive.
That means it is up to you to design your hierarchy of objects in a way that clients can never face a case where an internal weak pointer is invalid, and that dropping every reference actually leads to the destruction of the hierarchy.
The solution actually resides in the details of your object hierarchy, and SWIG cannot do much about it.
Related
In our app we're about to (finally..) switch from raw pointers to using C++11 smart_ptr templates.
We do have the occasional bug in our app with (non C++) objects still keeping references to our C++ objects causing crashes in the past when accessing the then-dealloc'd objects.
Not sure if this is a silly question - but is there a way to take advantage of the smart_ptr objects and 'dump' the objects still holding on to the C++ objects when none are expected to hold a reference to one any more?
I guess what I'm asking for is a way to list all owners of smart_ptr<MyClass> at a certain point in time.
Any suggestions much appreciated!
No. Without creating your own smart pointer classes that wrap std::unique_ptr and std::shared_ptr (ignore the deprecated std::auto_ptr) that tracks this information, there is no way to do that.
The standard classes themself do not track this information (would be too costly).
Another alternative would be to modify the code of your standard library implementation to track that info. Less invasive on your code since you can keep using the standard names. But probably a bit more tricky than just wrapping the classes and use the wrappers.
Don't believe this is possible for any out of the box c++ smart pointers. You can trivially wrap a shared_ptr to achieve the same effect though.
template<typename T>
class mySmartPtr : boost::noncopyable{
public:
// This method should be the only way this object can be copied
// as the copy constructors are made private
// The newOwnerName parameter can be used to populate m_onwers.
static mySmartPtr<T> newOwner(mySmartPtr<T>&, std::string newOnwerName);
private:
std::shared_ptr<T> m_ptr;
static std::vector<std::string> m_owners;
};
We do have the occasional bug in our app with (non C++) objects still keeping references to our C++ objects causing crashes in the past when accessing the then-dealloc'd objects.
This is serious and must not be ignored.
If you're giving 3rd party library components observer status on your objects, then it stands to reason that the 3rd party component's observer must not outlive your object.
There are 3 common causes for this problem:
Improper lifetime management of the 3rd-party component (you're deleting the observed object before shutting down the 3rd party observer)
improperly detected crossing cases (resulting in 1, above)
In the case were you are the component, you must take orders on from the 3rd party framework as to when you may dispose of your object.
Before involving shared_ptrs you ought to first prove that the shared_ptr may legitimately destroy the object. If the 3rd party component has a 'deregister' method, then you can solve this by:
Ensure ownership of the 3rd party component and your observed object are controlled by the same shared_ptr, or
Use a custom deleter on the shared_ptr to cause de-registration on your controlled object on the 3rd party object before finally deleting it.
If none of this is clear, it's time to take a good long look at your object lifetimes. It often helps to draw sequence diagrams.
I've got some code that is using shared_ptr quite widely as the standard way to refer to a particular type of object (let's call it T) in my app. I've tried to be careful to use make_shared and std::move and const T& where I can for efficiency. Nevertheless, my code spends a great deal of time passing shared_ptrs around (the object I'm wrapping in shared_ptr is the central object of the whole caboodle). The kicker is that pretty often the shared_ptrs are pointing to an object that is used as a marker for "no value"; this object is a global instance of a particular T subclass, and it lives forever since its refcount never goes to zero.
Using a "no value" object is nice because it responds in nice ways to various methods that get sent to these objects, behaving in the way that I want "no value" to behave. However, performance metrics indicate that a huge amount of the time in my code is spent incrementing and decrementing the refcount of that global singleton object, making new shared_ptrs that refer to it and then destroying them. To wit: for a simple test case, the execution time went from 9.33 seconds to 7.35 seconds if I stuck nullptr inside the shared_ptrs to indicate "no value", instead of making them point to the global singleton T "no value" object. That's a hugely important difference; run on much larger problems, this code will soon be used to do multi-day runs on computing clusters. So I really need that speedup. But I'd really like to have my "no value" object, too, so that I don't have to put checks for nullptr all over my code, special-casing that possibility.
So. Is there a way to have my cake and eat it too? In particular, I'm imagining that I might somehow subclass shared_ptr to make a "shared_immortal_ptr" class that I could use with the "no value" object. The subclass would act just like a normal shared_ptr, but it would simply never increment or decrement its refcount, and would skip all related bookkeeping. Is such a thing possible?
I'm also considering making an inline function that would do a get() on my shared_ptrs and would substitute a pointer to the singleton immortal object if get() returned nullptr; if I used that everywhere in my code, and never used * or -> directly on my shared_ptrs, I would be insulated, I suppose.
Or is there another good solution for this situation that hasn't occurred to me?
Galik asked the central question that comes to mind regarding your containment strategy. I'll assume you've considered that and have reason to rely on shared_ptr as a communical containment strategy for which no alternative exists.
I have to suggestions which may seem controversial. What you've defined is that you need a type of shared_ptr that never has a nullptr, but std::shared_ptr doesn't do that, and I checked various versions of the STL to confirm that the customer deleter provided is not an entry point to a solution.
So, consider either making your own smart pointer, or adopting one that you change to suit your needs. The basic idea is to establish a kind of shared_ptr which can be instructed to point it's shadow pointer to a global object it doesn't own.
You have the source to std::shared_ptr. The code is uncomfortable to read. It may be difficult to work with. It is one avenue, but of course you'd copy the source, change the namespace and implement the behavior you desire.
However, one of the first things all of us did in the middle 90's when templates were first introduced to the compilers of the epoch was to begin fashioning containers and smart pointers. Smart pointers are remarkably easy to write. They're harder to design (or were), but then you have a design to model (which you've already used).
You can implement the basic interface of shared_ptr to create a drop in replacement. If you used typedefs well, there should be a limited few places you'd have to change, but at least a search and replace would work reasonably well.
These are the two means I'm suggesting, both ending up with the same feature. Either adopt shared_ptr from the library, or make one from scratch. You'd be surprised how quickly you can fashion a replacement.
If you adopt std::shared_ptr, the main theme would be to understand how shared_ptr determines it should decrement. In most implementations shared_ptr must reference a node, which in my version it calls a control block (_Ref). The node owns the object to be deleted when the reference count reaches zero, but naturally shared_ptr skips that if _Ref is null. However, operators like -> and *, or the get function, don't bother checking _Ref, they just return the shadow, or _Ptr in my version.
Now, _Ptr will be set to nullptr (or 0 in my source) when a reset is called. Reset is called when assigning to another object or pointer, so this works even if using assignment to nullptr. The point is, that for this new type of shared_ptr you need, you could simply change the behavior such that whenever that happens (a reset to nullptr), you set _Ptr, the shadow pointer in shared_ptr, to the "no value global" object's address.
All uses of *,get or -> will return the _Ptr of that no value object, and will correctly behave when used in another assignment, or reset is called again, because those functions don't rely upon the shadow pointer to act upon the node, and since in this special condition that node (or control block) will be nullptr, the rest of shared_ptr would behave as though it was pointing to nullptr correctly - that is, not deleting the global object.
Obviously this sounds crazy to alter std::pointer to such application specific behavior, but frankly that's what performance work tends to make us do; otherwise strange things, like abandoning C++ occasionally in order to obtain the more raw speed of C, or assembler.
Modifying std::shared_ptr source, taken as a copy for this special purpose, is not what I would choose (and, factually, I've faced other versions of your situation, so I have made this choice several times over decades).
To that end, I suggest you build a policy based smart pointer. I find it odd I suggested this earlier on another post today (or yesterday, it's 1:40am).
I refer to Alexandrescu's book from 2001 (I think it was Modern C++...and some words I don't recall). In that he presented loki, which included a policy based smart pointer design, which is still published and freely available on his website.
The idea should have been incorporated into shared_ptr, in my opinion.
Policy based design is implemented as the paradigm of a template class deriving from one or more of it's parameters, like this:
template< typename T, typename B >
class TopClass : public B {};
In this way, you can provide B, from which the object is built. Now, B may have the same construction, it may also be a policy level which derives from it's second parameter (or multiple derivations, however the design works).
Layers can be combined to implement unique behaviors in various categories.
For example:
std::shared_ptr and std::weak_ptrare separate classes which interact as a family with others (the nodes or control blocks) to provide smart pointer service. However, in a design I used several times, these two were built by the same top level template class. The difference between a shared_ptr and a weak_ptr in that design was the attachment policy offered in the second parameter to the template. If the type is instantiated with the weak attachment policy as the second parameter, it's a weak pointer. If it's given a strong attachment policy, it's a smart pointer.
Once you create a policy designed template, you can introduce layers not in the original design (expanding it), or to "intercept" behavior and specialize it like the one you currently require - without corrupting the original code or design.
The smart pointer library I developed had high performance requirements, along with a number of other options including custom memory allocation and automatic locking services to make writing to smart pointers thread safe (which std::shared_ptr doesn't provide). The interface and much of the code is shared, yet several different kinds of smart pointers could be fashioned simply by selecting different policies. To change behavior, a new policy could be inserted without altering the existing code. At present, I use both std::shared_ptr (which I used when it was in boost years ago) and the MetaPtr library I developed years ago, the latter when I need high performance or flexible options, like yours.
If std::shared_ptr had been a policy based design, as loki demonstrates, you'd be able to do this with shared_ptr WITHOUT having to copy the source and move it to a new namespace.
In any event, simply creating a shared pointer which points the shadow pointer to the global object on reset to nullptr, leaving the node pointing to null, provides the behavior you described.
I'm primarily a C++ programmer, and I've grown used to having class templates like std::unique_ptr, std::shared_ptr, etc for expressing ownership of my objects. Does Delphi have anything that is similar in its standard library? Are there any best-practices out there for expressing object ownership that I should be following as I write my code?
Edit: Since C++11 became standard, there are two lightweight helper classes, std::shared_ptr and std::unique_ptr.
If I create a variable of type std::shared_ptr<int>, it represents a pointer to an int with shared ownership: under the hood is reference-counted, and when the ref-count reaches zero then the pointer is automatically freed. This type expresses a kind of "shared ownership", where many objects share the responsibility of destroying the resource when they are done with it.
In contrast, std::unique_ptr expresses single ownership. When the unique_ptr goes out of scope, the resource is automatically freed. std::unique_ptr cannot be copied: there can be exactly one object owning this resource at a time, and there is exactly one object who is responsible to clean the object up.
Contrast these lightweight classes with a naked pointer to int, where it can represent either shared ownership, unique ownership, or it can just be a reference to an object somewhere else! The type tells you nothing.
My question is: as Delphi supports holding references to objects, are there any mechanisms for explicitly stating "I am the sole owner of this object, when I'm done with it, I will free it", vs "I am merely keeping a reference to this object around for the purpose of interacting with it, but somebody else will clean it up" vs "I share this object with many other objects, and whoever has it last gets to clean it up."
I know that Collections.Generics has different collections such as TList vs TObjectList, where TObjectList will free the members stored within it, but TList won't. You can say that TObjectList "owns" it's elements, whereas TList doesn't. This is the essence of my question, really. When designing my own classes, are there ways of directly expressing these kinds of ownership issues within the language? Or are there any best practices/naming conventions that are common amongst developers?
I am not aware of any language constructs that can help, nor of any "standard naming conventions".
However, long ago, I have adopted the following naming convention to make it easier to check whether classes clean up behind themselves properly:
As per the standard Delphi convention all field names start with an "F".
Object references for which the class has / takes on life time management responsibility, start with "FMy".
Interface references the class should release explicitly, by setting the reference to nil in the destructor (for performance, to break a cyclic dependency, etc.) start with "FMi"
Very crude, but it works, and has helped a lot when going through code you haven't seen in a while to prevent those "Wait, shouldn't that reference be freed or nilled?" searches.
std::unique_ptr cannot be copied: there can be exactly one object owning this resource at a time
In the Delphi language, there is no type nor mechanism that prevents to share 'ownership'. A copy of any reference can always be made. (Read: there's nothing in Delphi that allows you to block assignment, as David nicely put it.)
When the unique_ptr goes out of scope, the resource is automatically freed.
In Delphi, this is only possible with (or via) interfaces. Delphi has no garbage collector.
And there is exactly one object who is responsible to clean the object up.
Responsibility for cleaning up you have to enforce by yourself. Or delegate that task to a(nother) framework. For example, the default Delphi VCL class TComponent implements automatic ownership (and destruction) that can optionally be exchanged/controlled with RemoveComponent and InsertComponent.
When designing my own classes, are there ways of directly expressing these kinds of ownership issues within the language? Or are there any best practices/naming conventions that are common amongst developers?
Not exactly on topic, but certainly related: there are multiple 'singleton' design pattern implementations that enforce single-time creation of objects.
Regarding naming conventions: the term "Owner" (or "OwnsObjects" from your own example) definitely expresses ownership in the sense that that owner will take care of destruction when necessary. Thus a button created with a form as owner (the single parameter of the button's default constructor) needs no manual destruction.
The concepts in Delphi differ from C++ in many occasions. Both languages are third generation, but Delphi likes to work on a higher level of abstraction than C++. For instance, Delphi supports pointers but they are rarely used when campared to the concept of reference, which is not precisely the same one as in C++.
In Delphi, object variables are in fact references (or in a lower level of abstraction, they are pointers). In C++, when you declare an object variable, the constructor is invokated imediatly, in Delphi it´s not and you have to call it in a given moment, what will allocate memory and run the constructor. So, the memory management of objects in C++ and Delphi are conditionated to different life cycles.
All this was said just to tell you that the memory management design style in Delphi is different than C++. That´s why Delphi doesn´t have any helper class that does precisely what you want. However, Delphi provides a concept named Interfaces, that do not exist in C++ (at least, it didn´t when I used to work with C++, ages ago). Interfaces are similar to an abstract class in the sense they do not have code. You have to provide a class implementor to a interface and that class will provide the code. However, Interfaces provide a reference-count memory management that, I believe, is close to what your are looking for.
So, my answer to you is: the closest language construct that Delphi has to offer you in terms of memory management that can be used to your purposes is Interfaces. So, I suggest that you study it at least a bit to get your own conclusions.
In my application, I'm hooking various functions for creating COM objects (such as CoCreateInstanceEx) to get notified whenever some object is created. I'm keeping track of all created objects in a std::list and I'm iterating over that list to do various things (like checking which OLE objects have been activated).
The issue with this is that right now, whenever adding an IUnknown pointer to my list, I call IUnknown::AddRef on it to make sure that it doesn't get destroyed while I'm tracking it. That's not what I really want though; the lifetime of the object should be as long (or short) as it is without my tracing code, so I'd rather like to maintain a weak reference on the objects. Whenever the last reference to some tracked COM object is removed (and thus the object gets destroyed), I'd like to get notified so that I can update my bookkeeping (e.g. by setting the pointer in my list to NULL).*
What's the best way to do this? Right now, I'm patching the (first) VTable of all created objects so that the calls to IUnknown::Release via the first vtable get notified. However, this won't work for COM interfaces which inherit from multiple interfaces (and thus have multiple vtables), but I'm not sure whether this is really a problem: given the Rules for Implementing QueryInterface, there should always be just one IUnknown returned by IUnknown::QueryInterface, right? So I could do that and then patch that vtable.
Furthermore, this approach is also a bit hairy since it involves creating thunks which generate some code. I only implemented this for 32bit so far. Not a big issue, but still.
I'm really wondering whether there isn't a more elegant way to have a weak reference to a COM object. Does anybody know?
*: The next thing I'll have to solve is making this work correctly in case I have active iterators (I'm using custom iterator objects) traversing the list of COM objects. I may need to keep track of the active iterators and once the last one finished, remove all null pointers from the list. Or something like that.
This isn't an answer as much as a set of issues why this is a really tricky thing to do - I'm putting it in as an answer since there's too much information here than fits in a comment :)
My understanding is that the concept of weak reference just doesn't exist in COM, period. You've got reference counting via IUnknown, and that's the sum total of how COM deals with object lifetime management. Anything beyond that is, strictly speaking, not COM.
(.Net does support the concept, but it's got an actual GC-based memory manager to provide appropriate support, and can treat WeakRef objects differently than regular references in memory. But that's not the case with the very simple world that COM assumes, which is a world of plain memory and pointers, and little more.)
COM specifies that reference counting is per-interface; any COM object is free to do ref counting per object as a convenience, but the upshot is that if you're wrapping an object, you have to assume the most restrictive case. So you cannot assume that any given IUnknown will be used for all addrefs/releases on that object: you'd really need to track each interface separately.
The canonical IUnknown - the one you get back by QI'ing for IUnknown - could be any interface at all - even a dedicated IUnknown that is used only for the purpose of acting as an identity! - so long as the same binary pointer value is returned each time. All other interfaces could be implemented any way; typically the same value is returned each time, but a COM object could legitimately return a new IFoo each time someone QI's for IFoo. Or even keep around a cache of IFoos and return one at random.
...and then you've got aggregation to deal with - basically, COM doesn't have a strong concept of object at all, it's all about interfaces. Objects, in COM, are just a collection of interfaces that happen to share the same canonical IUnknown: they might be implemented as a single C/C++ object behind the scenes, or as a family of related C/C++ objects presenting a facade of a 'single COM object'.
Having said all of that, given that:
I'm tracing the state of various components (including all COM objects) of this software for the sake of debugging
Here's an alternate approach that might produce some useful data to debug with.
The idea here is that many implementations of COM objects will return the ref count as the return value to Release() - so if they return 0, then that's a clue that the interface may have been released.
This is not guaranteed, however: as MSDN states:
The method returns the new reference count. This value is intended to be used only for test purposes.
(emphasis added.)
But that's apparently what you're doing here.
So one thing you could do, assuming you own the calling code, is to replace calls with Release() with an inline called MyRelease() or similar that will call release, and if it notices that the return value is 0, then notes that the interface pointer is now possibly freed - removes it from a table, logs it to a file, etc.
One major caveat: keep in mind that COM does not have a concept of weak ref, even if you try to hack something together. Using a COM interface pointer that has not been AddRef()'d is illegal as far as COM is concerned; so if you save away interface pointer values in any sort of list, the only thing you should so with those is treat them as opaque numbers for debugging purposes (eg. log them to a file so you can correlate creates with destroys, or keep track of how many you have outstanding), but do not attempt to use them as actual interface pointers.
Again, keep in mind that nothing requires a COM object to follow the convention of returning the refcount; so be aware that you could see something that looks like a bug but is actually just an implementation of Release just happens to always returns 0 (or rand(), if you're especially unlucky!)
First, you're right that QueryInterface for IUnknown should always return the same pointer; IUnknown is treated as the object's identity IIRC, so needs to be stable.
As for weak pointers, off the top of my head, maybe you could give CoMarshalInterThreadInterfaceInStream a whirl? It is meant to allow you to serialize a reference to a COM object into a stream, then create a new reference to the object on some other thread using the stream. However, if you serialise into a stream and retain the stream as a sort of weak pointer, then unmarshal later on to recover the pointer, you could check whether unmarshalling fails; If so, the object is gone.
With WinRT IWeakReference was added to enable weak refs to COM objects. Objects created with WRL's RuntimeClass support IWeakReference by default (can be disabled with an option).
you can use IWeakReference in your designs but it means you will need to use at least some WinRT concepts, IInspectable based interface.
I have written a library that exposes references to several related object types. All of these objects have their lifetimes managed by the library internally via boost::shared_ptr
A user of the library would also be able to know, by nature of the library, the lifetimes of any of the exposed objects. So they could store pointers or keep references to these objects. It would be reasonable for them to do this and know when those objects are no longer valid.
But I feel guilty forcing my users to be reasonable.
Is it acceptable to have a library expose weak_ptr's to its objects? Have other libraries done this?
I have profiled this library's usage in apps and have found it to be too mission-critical to expose weak_ptr exclusively.
Would it be wiser to have matching API functions expose either a reference or a weak_ptr or to make any object capable of exposing a weak_ptr to itself?
If the smart_ptrs are already directly accessible to the library's users, then they've already got access to the weak_ptrs, simply via the corresponding weak_ptr's constructor. But if the smart_ptrs are all internal to the library, that's a different story.
In that case, I'd recommend letting each object pass out weak_ptrs to itself, in addition to any other access your library offers. That gives the users the most flexibility: if they need a weak_ptr, they've got immediate access to it; if they need a shared_ptr, they can easily get it; and if they just need access to the object itself, they can ignore the smart pointers entirely.
Of course, I don't know what your library does or how it's used or designed. That might change my recommendation.
Coming up with convoluted mechanisms to get at the objects of your library will only result in people not using your library. If the semantics of the library dictate you need to have people using weak_ptrs, there no way around the user knowing that the objects may go away at some point. Make the interface express as much information about the usage of the library as possible, keeps documentation down and makes it infinitely easier to use.
You can't design around bad/inexperienced users.
If you give your clients access to weak_ptrs they can just lock them to create shared_ptrs and end up delaying the destruction of objects. That might cause problems with your library.
I suggest wrapping a weak_ptr in some other class and giving the caller a shared_ptr to that. That way they can't just call weak_ptr<T>::lock(). You seem to have performance constraints that might influence how you implement it, but a shared_ptr<InterfaceClass> might be a good way to go, and keep the class with the weak_ptr internal to your library.
That way you also keep these implementation details out of your library interface and you can change the way you implement it without changing your interface.
I don't see any problem with exposing weak_ptrs, especially given that TR1 has similar smart pointers (PDF).
TR1 is largely implemented by Visual Studio and GCC, but not some of the other compilers out there. But when it's implemented in all the compilers you care about, you may want to rework the API to expose those smart pointers instead.
If you want to both trap invalid use of the library (trying to access the objects when they have been deleted) as well as have a high-performance API (no weak_ptr's and shared_ptr's in the API), then you could consider have a different API for debug and nondebug builds.
Let's suppose for simplicity that you have only one class of objects you expose; call this class Object. The pointer type which you return from the API for accessing the internal objects is then defined as:
#ifdef DEBUG
typedef ObjectPtrFacade ObjectPtr
#else
typedef Object * ObjectPtr;
#endif
Here the facade is class which you write. It works roughly like this:
class ObjectPtrFacade {
public:
ObjectPtrFacade(Object *o) : wptr(o) { }
// copy constructor and assignment here etc. (not written)
Object * operator -> () const { return access(); }
Object & operator * () const { return *access(); }
private:
Object * access() {
assert(wptr.use_count() > 0);
return (Object *)(wptr.lock());
}
weak_ptr<Object> wptr;
}
In this way, whenever you build a debugging build, you have a special kind of smart pointer in use which asserts before accessing the object that its use_count() is higher than zero, i.e. that the object still exists. If the object has been released, you get a failing assert, which is better than a null pointer reference.
In general of course it is so that using weak_ptr's does not help if you have "stupid" users of the API, because they could call lock() and then still make a null-pointer reference after the weak_ptr returns a shared_ptr which is empty...