Boost logo

Boost :

Subject: Re: [boost] [interest] rich-typed smart pointers
From: Julian Gonggrijp (j.gonggrijp_at_[hidden])
Date: 2013-10-07 06:01:31


Gavin Lambert wrote:

> On 10/6/2013 8:34 AM, Quoth Julian Gonggrijp:
>> As for safety, I think std::weak_ptr is not really safer that rtp::weak_ptr
>> because it's just as easy to produce a dangling pointer (in fact std takes
>> only 3 lines of code to do it while rtp requires 4) and that's a disaster no
>> matter what. The fact that it can detect that it's dangling does however
>> make it easier to debug.
>
> I fail to see why "dangling pointers" are a disaster with std::weak_ptr.
>
> Their implementation does not permit any access without locking the pointer, which will either succeed (and consequently prevent the object from being destroyed while it is being accessed) or fail (if the object has already been destroyed) and return a null pointer.
>
> The code using the pointer has to be able to cope gracefully with failure to obtain a pointer, but this is built into the semantics of weak_ptrs -- if you can't write the code such that it can fail gracefully, then you should have been using a shared_ptr instead so that you can guarantee that the object won't disappear before you're ready for it to do so.

The std::weak_ptr detects the dangling pointer and changes it into a
null pointer. This makes sense, because null pointers are easier to
detect. However, as the surrounding code probably relies on a live
pointer (because dangling pointers are never planned) the program is
still going to fail. This is what I meant by "disaster".

You say that the caller should have been using std::shared_ptr
instead, but similar reasoning applies to the rtp pointers. All
pointers (smart and raw) are associated with pitfalls that the user
has to avoid. Now, you would be right to point out that I haven't
properly spelled out the pitfalls for the rtp pointers; I will fix
that omission in the next alpha version.

Further note that the user probably chose std::weak_ptr in the first
place in order to avoid cyclic ownership. If the only way to avoid the
dangling pointer is to switch back to std::shared_ptr, this boils down
to a choice between two evils: a dangling pointer or a memory leak.

Fortunately this will usually not be the case, because (I believe)
dangling pointers can always be avoided with more careful program
logic. This however is equally true of the rtp pointers.

>
> Bare pointers, on the other hand (including rtp::weak_ptr, from what I understand from this discussion, though I haven't examined the code specifically) have no such tracking/locking capability

Please forgive me for nagging about terminology, but rtp::weak_ptr
should really be thought of as a smart pointer. It is a wrapper around
a raw pointer that helps to take ownership management out of the
user's hands, in this case by ensuring that the corresponding
rtp::owner_ptr (or rtp::data_ptr) is the only entity that can
deallocate the object. If you think that a smart pointer must on top
of that be able to track whether a pointer is still live, you have
effectively equated "smart pointer" to "reference-counted pointer" and
you are forced to subscribe to the view that std::unique_ptr is a
"bare" pointer.

> so there is no way to ensure that a particular pointer value still points at the same object as it originally did.
>
>
> Sure, it's still possible to get a null pointer access with std::weak_ptr, by locking one and then accessing the resulting shared_ptr without checking for validity (ie. lazy programmer). But in this case it will assert, and even failing that null accesses are far easier to track down and deal with than non-null-invalid-object accesses.
>
> (I'm not saying that shared_ptrs don't have problems -- for example it's far too easy to get into trouble with cyclic references if you're not careful, and I've yet to find any good tools to track these down. But they don't have *this* particular problem, since solving that is pretty much their entire reason for existing in the first place.)

They don't have the specific problem that dangling pointers are hard
to track down, thanks to reference counting, because dangling pointers
change into null pointers on the spot. I think calling that the sole
purpose of std::shared_ptr and std::weak_ptr would be giving them too
little credit, they can do much more for the user than just that.
Still, as you say, there are serious problems associated with them and
I believe this is sufficient reason to look into different approaches.

-Julian


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk