Boost logo

Boost :

From: Valentin Bonnard (Bonnard.V_at_[hidden])
Date: 2000-03-09 10:58:04


John Panzer wrote:

> Miki Jovanovic wrote:

> > So your code should simply become:
> >
> > void doit()
> > {
> > _ptr<Worker> temp( w );
> > temp->work();
> > }
>
> Leaving aside the issues in the rest of this thread, I like this idiom
> fine. However, if you have a bare pointer in the first place (such as
> "this"), a non-intrusive smart pointer is dangerous:
>
> void Worker::doit()
> {
> _ptr<Worker> temp(this); // Assumes no other smart ptrs exist...
> work(); // Don't need to use smart ptr, it just has to exist.
> }
>
> (The problem: If there is actually another non-intrusive smart pointer
> pointing at "*this", then you end up with two independent reference counts
> and a double deletion.)

This is yet another way to write ``delete this''.

> This is a recurring worry of mine wrt non-intrusive smart pointers; can
> anyone allay my fears about this? Is there any way to either

> Or (3) do people not feel that this is a real issue?

I feel that the issue is to teach people to read the doc.

The doc of _ptr is quite explicit about what _ptr does and
doesn't do. In particular, constructing a _ptr with a raw
pointer *always takes ownership*.

It's a simple fact that giving away what you don't own is a
steal. Constructing a _ptr from a raw pointer you aren't
responsible to delete is wrong.

The only problem I see is with people who are randomly salting
their code with _ptr just to feel better (they may feel better,
but their code won't _work_ better).

> (1) Disallow this, or
> (2) Allow it and make it safe?

Indeed it is possible to detect such cases: all we need is a
global database of objects owned by _ptr. Then, when a _ptr is
initialised with a raw pointer, it could check in the database
to see if the object is already owned. Then it could either
shared the object with the existing owner or throw an exception.

For polymorphic smart-pointers (like shared_ptr), this needs
two different smart-pointers: one of polymorphic objects, one
for non-polymorphic ones. This would mean that we introduce
poly_shared_ptr and mono_shared_ptr; this would break and
complicate the interface.

I don't see _any_ reasons to do so and annoy every user for
some sloppy programmers. Initialising an owning smart-ptr with
a pointer we don't own is not a practice we want to promote.

When a function foo (T* p) called, foo can expect
the pointer p to remain valid for the duration of
the function or until foo deletes p (unless otherwise
specified in the interface of the function).
The function does not have to manipulate any smart pointer
for this purpose, this is a fundamental guaranty.

If a member function ``commits suicide'' (that is, delete this),
it should understand the consequences.

Short answer: this is a non-problem, and we aren't going
              to break working code to solve it.

-- 
Valentin Bonnard

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