Boost logo

Boost :

From: Peter Dimov (pdimov_at_[hidden])
Date: 2002-05-16 05:44:55


From: "hicks" <hicks_at_[hidden]>
> Hi Peter,
>
> you wrote
>
> /Consider this example:
> /weak_ptr<T> wp;
> /
> /// ...
> /
> /if(wp.get() != 0)
> /{
> / wp->f();
> / wp->g();
> /}
>
> and also
>
> /Looks innocent enough, but wp->f() may invalidate wp (by resetting the
> /shared_ptr holding the object), and wp->g() will crash.
> /The intended use pattern is for clients to take ownership only
> temporary, as
> /if holding a lock on the object; clearly, the object shouldn't go away in
> /the middle of a "transaction."
>
>
> If the design is such that wp may be invalidated in f(),
> then it should be up to the user to decide whether wp->g()
> should cause an error, or processing should continue.
> The implications of silently continuing (as is posiible with a temporary
> smart pointer) may be worse than a
> pointer access violation. You can't say a priori.
> The code can be simply fixed by writing
> if(wp.get() != 0)
> {
> wp->f();
> if (wp.get()) wp->g();
> else (...)
> }
> which actually does a lot more to make clear what is going on in that
> application
> than forcing heavy policy on the user.

The example is illustrative. Real code would be something like:

void T::f()
{
    ::f2();
    this->g();
    this->h();
}

if(wp.get() != 0) wp->f();

where ::f2() can indirectly invalidate wp. You can't defend against it
inside T::f.

This may seem contrived, but it did actually happen to me. ::f2() caused -
indirectly - the Windows message WM_CANCELMODE (that signals end of mouse
capture and should end any dragging) to be sent, which in turn caused

s_drag_handler.reset();

to be called, and it so happened that I was in a member function of said
drag_handler at the time.

Believe me, you don't want to chase such bugs. Or make the user defend
against them.


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