<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Issue 998: Smart pointer referencing its owner</title>
<meta property="og:title" content="Issue 998: Smart pointer referencing its owner">
<meta property="og:description" content="C++ library issue. Status: C++11">
<meta property="og:url" content="https://cplusplus.github.io/LWG/issue998.html">
<meta property="og:type" content="website">
<meta property="og:image" content="http://cplusplus.github.io/LWG/images/cpp_logo.png">
<meta property="og:image:alt" content="C++ logo">
<style>
  p {text-align:justify}
  li {text-align:justify}
  pre code.backtick::before { content: "`" }
  pre code.backtick::after { content: "`" }
  blockquote.note
  {
    background-color:#E0E0E0;
    padding-left: 15px;
    padding-right: 15px;
    padding-top: 1px;
    padding-bottom: 1px;
  }
  ins {background-color:#A0FFA0}
  del {background-color:#FFA0A0}
  table.issues-index { border: 1px solid; border-collapse: collapse; }
  table.issues-index th { text-align: center; padding: 4px; border: 1px solid; }
  table.issues-index td { padding: 4px; border: 1px solid; }
  table.issues-index td:nth-child(1) { text-align: right; }
  table.issues-index td:nth-child(2) { text-align: left; }
  table.issues-index td:nth-child(3) { text-align: left; }
  table.issues-index td:nth-child(4) { text-align: left; }
  table.issues-index td:nth-child(5) { text-align: center; }
  table.issues-index td:nth-child(6) { text-align: center; }
  table.issues-index td:nth-child(7) { text-align: left; }
  table.issues-index td:nth-child(5) span.no-pr { color: red; }
  @media (prefers-color-scheme: dark) {
     html {
        color: #ddd;
        background-color: black;
     }
     ins {
        background-color: #225522
     }
     del {
        background-color: #662222
     }
     a {
        color: #6af
     }
     a:visited {
        color: #6af
     }
     blockquote.note
     {
        background-color: rgba(255, 255, 255, .10)
     }
  }
</style>
</head>
<body>
<hr>
<p><em>This page is a snapshot from the LWG issues list, see the <a href="lwg-active.html">Library Active Issues List</a> for more information and the meaning of <a href="lwg-active.html#C++11">C++11</a> status.</em></p>
<h3 id="998"><a href="lwg-defects.html#998">998</a>. Smart pointer referencing its owner</h3>
<p><b>Section:</b> 20.3.1.3.6 <a href="https://wg21.link/unique.ptr.single.modifiers">[unique.ptr.single.modifiers]</a> <b>Status:</b> <a href="lwg-active.html#C++11">C++11</a>
 <b>Submitter:</b> Pavel Minaev <b>Opened:</b> 2009-02-26 <b>Last modified:</b> 2016-01-28</p>
<p><b>Priority: </b>Not Prioritized
</p>
<p><b>View all other</b> <a href="lwg-index.html#unique.ptr.single.modifiers">issues</a> in [unique.ptr.single.modifiers].</p>
<p><b>View all issues with</b> <a href="lwg-status.html#C++11">C++11</a> status.</p>
<p><b>Discussion:</b></p>
<p>
Consider the following (simplified) implementation of 
<code>std::auto_ptr&lt;T&gt;::reset()</code>: 
</p>

<blockquote><pre>
void reset(T* newptr = 0) { 
   if (this-&gt;ptr &amp;&amp; this-&gt;ptr != newptr) { 
     delete this-&gt;ptr; 
   } 
   this-&gt;ptr = newptr; 
} 
</pre></blockquote>

<p>
Now consider the following code which uses the above implementation: 
</p>

<blockquote><pre>
struct foo { 
   std::auto_ptr&lt;foo&gt; ap; 
   foo() : ap(this) {} 
   void reset() { ap.reset(); } 
}; 
int main() { 
   (new foo)-&gt;reset(); 
} 
</pre></blockquote>

<p>
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: 
</p>

<ol>
<li>
<code>foo::reset()</code> entered 
</li>
<li>
<code>auto_ptr::reset()</code> entered 
</li>
<li>
<code>auto_ptr::reset()</code> tries to delete <code>foo</code>
</li>
<li>
<code>foo::~foo()</code> entered, tries to destruct its members 
</li>
<li>
<code>auto_ptr::~auto_ptr()</code> executed - <code>auto_ptr</code> is no longer a valid object! 
</li>
<li>
<code>foo::~foo()</code> left 
</li>
<li>
<code>auto_ptr::reset()</code> sets its "ptr" field to 0 &lt;- U.B.! <code>auto_ptr</code>
is not a valid object here already! 
</li>
</ol>

<p><i>[
Thanks to Peter Dimov who recognized the connection to <code>unique_ptr</code> and
brought this to the attention of the LWG, and helped with the solution.
]</i></p>


<p><i>[
Howard adds:
]</i></p>


<blockquote><p>
To fix this behavior <code>reset</code> must be specified such that deleting the
pointer is the last action to be taken within <code>reset</code>.
</p></blockquote>

<p><i>[
Alisdair adds:
]</i></p>


<blockquote>
<p>
The example providing the rationale for LWG <a href="lwg-defects.html#998" title="Smart pointer referencing its owner (Status: C++11)">998</a><sup><a href="https://cplusplus.github.io/LWG/issue998" title="Latest snapshot">(i)</a></sup> 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.
</p>
<p>
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.
</p>
</blockquote>

<p><i>[
Batavia (2009-05):
]</i></p>

<blockquote>
<p>
Howard summarizes:
</p>
<blockquote><p>
This issue has to do with circular ownership,
and affects <code>auto_ptr</code>, 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.
</p></blockquote>
<p>
Howard points to message c++std-lib-23175 for another example,
requested by Alisdair.
</p>
<p>
We agree with the issue and with the proposed resolution.
Move to Tentatively Ready.
</p>
</blockquote>



<p id="res-998"><b>Proposed resolution:</b></p>
<p>
Change 20.3.1.3.6 <a href="https://wg21.link/unique.ptr.single.modifiers">[unique.ptr.single.modifiers]</a>, p5 (<i>Effects</i> clause for <code>reset</code>), and p6:
</p>

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

<p>
-6- Postconditions: <code>get() == p</code>.
<ins>[<i>Note:</i> The postcondition does not hold if the call to
<code>get_deleter()</code> destroys <code>*this</code> since <code>this-&gt;get()</code> is no longer a valid
expression. <i>-- end note</i>]</ins>
</p>
</blockquote>





</body>
</html>
