<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Issue 2384: Allocator's deallocate function needs better specification</title>
<meta property="og:title" content="Issue 2384: Allocator's deallocate function needs better specification">
<meta property="og:description" content="C++ library issue. Status: C++17">
<meta property="og:url" content="https://cplusplus.github.io/LWG/issue2384.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++17">C++17</a> status.</em></p>
<h3 id="2384"><a href="lwg-defects.html#2384">2384</a>. Allocator's <code>deallocate</code> function needs better specification</h3>
<p><b>Section:</b> 16.4.4.6 <a href="https://wg21.link/allocator.requirements">[allocator.requirements]</a> <b>Status:</b> <a href="lwg-active.html#C++17">C++17</a>
 <b>Submitter:</b> Daniel Kr&uuml;gler <b>Opened:</b> 2014-05-19 <b>Last modified:</b> 2017-07-30</p>
<p><b>Priority: </b>3
</p>
<p><b>View other</b> <a href="lwg-index-open.html#allocator.requirements">active issues</a> in [allocator.requirements].</p>
<p><b>View all other</b> <a href="lwg-index.html#allocator.requirements">issues</a> in [allocator.requirements].</p>
<p><b>View all issues with</b> <a href="lwg-status.html#C++17">C++17</a> status.</p>
<p><b>Discussion:</b></p>
<p>
According to Table 28, 16.4.4.6 <a href="https://wg21.link/allocator.requirements">[allocator.requirements]</a>, an <code>Allocator</code>'s <code>deallocate</code>
function is specified as follows:
</p>
<blockquote><p>
All <code>n</code> <code>T</code> objects in the area
pointed to by <code>p</code> shall be
destroyed prior to this call. <code>n</code>
shall match the value passed to
allocate to obtain this
memory. Does not throw
exceptions. [<i>Note</i>: <code>p</code> shall not be
singular. &mdash; <i>end note</i>]
</p></blockquote>
<p>
This wording is confusing in regard to the following points:
</p>
<ol>
<li><p>This specification does not make clear that the result of an <code>allocate</code>
call can only be returned once to the <code>deallocate</code> function. This is much
clearer expressed for <code>operator delete</code> (17.6.3.2 <a href="https://wg21.link/new.delete.single">[new.delete.single]</a> p12, emphasis mine):</p>
<blockquote><p>
<i>Requires</i>: <code>ptr</code> shall be a null pointer or <span style="color:#C80000;font-weight:bold">its value shall be a value returned 
by an earlier call to</span> the (possibly replaced) <span style="color:#C80000;font-weight:bold"><code>operator new(std::size_t)</code> or 
<code>operator new(std::size_t,const std::nothrow_t&amp;)</code> which has not been invalidated 
by an intervening call to <code>operator delete(void*)</code></span>.
</p></blockquote>
</li>
<li><p>The intended meaning of that wording was to say that <code>deallocate</code> shall accept <em>every</em> result value
that had been returned by a corresponding call to <code>allocate</code>, this includes also a possible result of a
null pointer value, which is possible ("[<i>Note</i>: If <code>n == 0</code>, the return value is unspecified.
&mdash; <i>end note</i>]"). Unfortunately the <code>deallocate</code> function uses a non-normative note ("<code>p</code> shall not be
singular.") which refers to the fuzzy term <code>singular</code>, that is one of the most unclear and misunderstood terms
of the library, as pointed out in <a href="lwg-active.html#1213" title="Meaning of valid and singular iterator underspecified (Status: Open)">1213</a><sup><a href="https://cplusplus.github.io/LWG/issue1213" title="Latest snapshot">(i)</a></sup>. The occurrence of this term has lead to the possible understanding,
that this function would never allow null pointer values. Albeit for allocators the intention had not been to require the support
<em>in general</em> that a null pointer value can be provided to <code>deallocate</code> (as it is allowed for <code>std::free</code>
and <code>operator delete</code>), the mental model was that <em>every</em> returned value of <code>allocate</code> shall be an
acceptable argument type of the corresponding <code>deallocate</code> function.
</p>
</li>
</ol>

<p>
This issue is not intending to enforce a specific meaning of <em>singular</em> iterator values, but the assertion is
that this note does more harm than good. In addition to wording from <code>operator delete</code> there is no longer any need
to obfuscate the normative wording. 
</p>

<p><i>[2014-05-24 Alisdair comments]</i></p>


<p>
Now that I am reading it very precisely, there is another mis-stated assumption
as a precondition for <code>deallocate</code>:
</p>
<blockquote><p>
All <code>n T</code> objects in the area pointed to by <code>p</code> shall be destroyed prior to this call.
</p></blockquote>
<p>
This makes a poor assumption that every possible object in the allocated buffer
was indeed constructed, but this is often not the case, e.g., a <code>vector</code> that is not
filled to capacity. We should require calling the destructor for only those objects
actually constructed in the buffer, which may be fewer than <code>n</code>, or even 0.
<p/>
I wonder if we really require all objects to be destroyed before calling <code>deallocate</code>
though. Are we really so concerned about leaking objects that might not manage
resources? Should this not be the proper concern of the library managing the
objects and memory?
</p>

<p><i>[2014-06-05 Daniel responds and improves wording]</i></p>


<p>
I fully agree with the last comment and I think that this requirement should be removed. We have no such
requirements for comparable functions such as <code>operator delete</code> or <code>return_temporary_buffer()</code>,
and this wording seems to be a wording rudiment that exists since C++98.
</p>

<p><i>[2015-05, Lenexa]</i></p>

<p>
Marshall: What do people think about this?<br/>
PJP: Sure.<br/>
Wakely: Love it.<br/>
Marshall: Ready?<br/>
Everyone agrees.<br/>
</p>


<p id="res-2384"><b>Proposed resolution:</b></p>

<p>This wording is relative to N3936.</p>

<ol>
<li><p>Change Table 28 ("<code>Allocator</code> requirements") as indicated:</p>

<blockquote>
<table border="1">
<caption>Table 28 &mdash; <code>Allocator</code> requirements</caption>
<tr>
<th align="center">Expression</th>
<th align="center">Return type</th>
<th align="center">Assertion/note<br/>pre-/post-condition</th>
<th align="center">Default</th>
</tr>

<tr>
<td colspan="4" align="center">
<code>&hellip;</code>
</td>
</tr>

<tr>
<td>
<code>a.deallocate(p,n)</code>
</td>
<td>
(not used)
</td>
<td>
<ins><i>Pre</i>: <code>p</code> shall be a value returned by an earlier<br/> 
call to <code>allocate</code> which has not been invalidated by<br/> 
an intervening call to <code>deallocate</code>. <code>n</code> shall<br/> 
match the value passed to <code>allocate</code> to obtain this<br/> 
memory.</ins> <del>All <code>n T</code> objects in the area pointed to by<br/> 
<code>p</code> shall be destroyed prior to this call.</del><br/>
<ins><i>Throws</i>: Nothing.</ins><del><code>n</code><br/>
shall match the value passed to<br/>
allocate to obtain this<br/>
memory. Does not throw<br/>
exceptions. [<i>Note</i>: <code>p</code> shall not<br/>
be singular. &mdash; <i>end note</i>]</del>
</td>
<td>
&nbsp;
</td>
</tr>

<tr>
<td colspan="4" align="center">
<code>&hellip;</code>
</td>
</tr>

</table>
</blockquote>

</li>
</ol>






</body>
</html>
