This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of C++11 status.

### 998. Smart pointer referencing its owner

Section: 20.3.1.3.6 [unique.ptr.single.modifiers] Status: C++11 Submitter: Pavel Minaev Opened: 2009-02-26 Last modified: 2016-01-28

Priority: Not Prioritized

View all other issues in [unique.ptr.single.modifiers].

View all issues with C++11 status.

Discussion:

Consider the following (simplified) implementation of `std::auto_ptr<T>::reset()`:

>     void reset(T* newptr = 0) {
>        if (this->ptr && this->ptr != newptr) {
>          delete this->ptr;
>        }
>        this->ptr = newptr;
>     }

Now consider the following code which uses the above implementation:

>     struct foo {
>        std::auto_ptr<foo> ap;
>        foo() : ap(this) {}
>        void reset() { ap.reset(); }
>     };
>     int main() {
>        (new foo)->reset();
>     }

With the above implementation of auto_ptr, this results in U.B. at the point of auto_ptr::reset(). If this isn't obvious yet, let me explain how this goes step by step:

1. `foo::reset()` entered
2. `auto_ptr::reset()` entered
3. `auto_ptr::reset()` tries to delete `foo`
4. `foo::~foo()` entered, tries to destruct its members
5. `auto_ptr::~auto_ptr()` executed - `auto_ptr` is no longer a valid object!
6. `foo::~foo()` left
7. `auto_ptr::reset()` sets its "ptr" field to 0 <- U.B.! `auto_ptr` is not a valid object here already!

[ Thanks to Peter Dimov who recognized the connection to `unique_ptr` and brought this to the attention of the LWG, and helped with the solution. ]

[ Howard adds: ]

> To fix this behavior `reset` must be specified such that deleting the pointer is the last action to be taken within `reset`.

[ Alisdair adds: ]

> The example providing the rationale for LWG 998 is poor, as it relies on broken semantics of having two object believing they are unique owners of a single resource. It should not be surprising that UB results from such code, and I feel no need to go out of our way to support such behaviour.

> If an example is presented that does not imply multiple ownership of a unique resource, I would be much more ready to accept the proposed resolution.

[ Batavia (2009-05): ]

> Howard summarizes:

> > This issue has to do with circular ownership, and affects `auto_ptr`, too (but we don't really care about that). It is intended to spell out the order in which operations must be performed so as to avoid the possibility of undefined behavior in the self-referential case.

> Howard points to message c++std-lib-23175 for another example, requested by Alisdair.

> We agree with the issue and with the proposed resolution. Move to Tentatively Ready.

Proposed resolution:

Change 20.3.1.3.6 [unique.ptr.single.modifiers], p5 (Effects clause for `reset`), and p6:

> -5- Effects: If `get() == nullptr` there are no effects. Otherwise `get_deleter()(get())`. Assigns `p` to the stored `pointer`, and then if the old value of the `pointer` is not equal to `nullptr`, calls `get_deleter()(`the old value of the `pointer)`. [Note: The order of these operations is significant because the call to `get_deleter()` may destroy `*this`. -- end note]

> -6- Postconditions: `get() == p`. [Note: The postcondition does not hold if the call to `get_deleter()` destroys `*this` since `this->get()` is no longer a valid expression. -- end note]