$include_dir="/home/hyper-archives/boost/include"; include("$include_dir/msg-header.inc") ?>
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.