Boost logo

Boost :

From: Tom Becker (voidampersand_at_[hidden])
Date: 2002-01-17 14:02:00


On Thu, 17 Jan 2002 14:13:33 +0200, "Peter Dimov" <pdimov_at_[hidden]> wrote:
>From: "David Abrahams" <david.abrahams_at_[hidden]>
> > struct Base { Base(); ~Base(); };
> > struct Derived : Base { Derived(); ~Derived(); };
> >
> > void unsafe()
> > {
> > shared_ptr<Derived> d(new Derived);
> > shared_ptr<Base> b(d);
> > d.reset();
> > b.reset(); // equivalent to delete (Base*)(new Derived)!!
> > };
>
>It recently occured to me that this is another example that proves release()
>extremely dangerous.
>
>A smart shared_ptr can do the right thing on b.reset(), but on b.release()
>the user will be left with a Base* and the undefined behavior is not far
>away.

The problem is not in shared_ptr or release.

     Derived* d = new Derived;
     Base* b = d;
     delete b; // ouch!

Deleting through a pointer that doesn't have adequate type
information is bad. The code should either give Base a virtual
destructor, or it should avoid slicing the Derived* to a Base*.
Converting the code to use shared_ptr doesn't change its safety, or
lack thereof, in any way.

In regards to other comments on release(), in an ideal world it would
not be necessary, but the real world contains other languages besides
C++, and legacy APIs that are not optional. Providing some control
over whether release() is exposed will only mean that the class can
conditionally be made useless.

Regards,

   Tom

-- 
Tom Becker                      "Within C++, there is a much smaller and
<voidampersand_at_[hidden]>        cleaner language struggling to get out."
                                                       -- Bjarne Stroustrup

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