Subject: Re: [boost] [smart_ptr] Interest in the missing smart pointer (that can target the stack)
From: Andrey Semashev (andrey.semashev_at_[hidden])
Date: 2016-02-02 04:19:48
On 2016-02-02 04:21, Gavin Lambert wrote:
> On 29/01/2016 23:25, Andrey Semashev wrote:
>> I think what Emil describes is a special case of a 'dangling_ptr' idiom,
>> if I may call it that way. The point is that there are cases when object
>> lifetime is controlled by a third party (e.g. the stack state, a foreign
>> library, etc.) and you need a safe way to know when the object has been
>> deleted. So you create a shared_ptr with a null_deleter pointing to that
>> object and save it in that object (or another storage associated with
>> that object). You keep only weak_ptrs to that object in all other places
>> in the code. When you need to use the object you have to lock a weak_ptr
>> and thus check if the object is still alive.
> The thing is that there is rarely a case in practice where doing this is
> actually beneficial, unless you have a bit of code that *usually* deals
> with "real" shared_ptrs in the full shared-ownership sense and you want
> to exercise them in a context where you know they won't be used
> concurrently -- eg. unit tests.
I also mentioned third party libraries (or APIs in general) which may or
may not delete your objects upon calling them. The approach may be the
easiest and safest way to know that the object has been deleted.
I do agree when all the code in question is under your control it is
better to avoid this idiom and use a design with proper ownership
semantics. But there are special cases when this trick comes handy.
> Typically single-threaded algorithms have a well-defined point at which
> the object is deleted (if this is a possibility), so it's not necessary
> to track this separately, and raw pointers/references are sufficient.
> (And if you're religiously opposed to having raw owning pointers, then
> use unique_ptr for the owning pointer and references for everything else.)
I'm not opposed to raw pointers, but when dealing with third party API I
would not rely on its documented/observed/reverse-engineered behavior
because it may change in a later version and may also be difficult to
replicate in my code. I just want to know when the actual deletion
happens, whenever it does.
> We've already established that making a copy of the shared_ptr to be
> used outside the call chain (eg. by another thread, or just by this
> thread in a later operation) is obviously unsafe.
It's not unsafe if that thread is guaranteed to not delete the object
(e.g. because the thread is blocked).
> Storing a weak_ptr in the single-threaded case is safe but pointless, as
> it should be obvious whether the object is alive or not during the
> initial operation (the code that deletes it can just store back a NULL,
> after all), and it will be guaranteed to be dead after that operation
> anyway. (This does assume that you have a known place to go to find
> that weak_ptr, rather than having lots of copies of it.)
That's right. Storing back-references to the places that refer to the
object is too tedious and intrusive. Remember that the back-references
should be managed too.
> Storing a weak_ptr in the multi-threaded case is unsafe, because such
> code expects to be able to promote one to a shared_ptr during some
> operation and for the underlying object to not be deleted while that
> operation is in progress, the latter of which is violated when the
> lifetime is not controlled by the shared_ptr itself.
True. The developer's job is to guarantee that that never happens.
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk