Boost logo

Boost :

From: David Abrahams (david.abrahams_at_[hidden])
Date: 2002-01-18 08:58:36


----- Original Message -----
From: "Peter Dimov" <pdimov_at_[hidden]>

> > struct Base { Base(); ~Base(); };
> > struct Derived : Base { Derived(); ~Derived(); };
> >
> > void unsafe()
> > {
> > shared_ptr<Base> b(new Derived);
>
> The expression "delete get()" invokes undefined behavior, therefore the
code
> is ill-formed.

1.3.14 well-formed program
a C++ program constructed according to the syntax rules, diagnosable
semantic rules, and the One Defini-
tion Rule (3.2).

So, I think "buggy" would be a better term here ;-)

> > b.reset(); // equivalent to delete (Base*)(new Derived)!!
> > };
> >
> > That's because, as long as shared_ptr<Base> allows construction from
> > a Derived*, it doesn't matter where the Derived* is obtained from.
> > Unfortunately, that means that tricks such as auto_ptr_ref can't save
> > us here.
> >
> > How about adding an additional constructor:
> >
> > template<typename Y>
> > explicit shared_ptr(Y* p);
>
> Doesn't help.
>
> Base * p = new Derived;
> shared_ptr<Base> b(p);

This is one reason I think it should be possible to configure a shared_ptr
so that it can't be constructed from a raw pointer. Here's another:

    shared_ptr<X> p(new X);
    f(p.get());

    void f(X* p)
    {
        shared_ptr<X> y(p); // double-deletion
    }

I've seen this mistake made by novices and experts alike.
Instead, there ought to be a family of static factory functions, so:

   shared_ptr<Y> p = shared_ptr<Y>::create(arg1, arg2, arg3);

is equivalent to:

    shred_ptr<Y> p(new Y(arg1, arg2, arg3));

-Dave


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