Skip to content

Commit 5eb76bb

Browse files
committed
Be more precies about array cookies; issue #119.
1 parent 7f36ec6 commit 5eb76bb

File tree

1 file changed

+95
-67
lines changed

1 file changed

+95
-67
lines changed

abi.html

Lines changed: 95 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -2111,86 +2111,114 @@ <h4><a href="#vtable-ctor-entries"> 2.6.4 Construction Virtual Table entries </a
21112111
<h3><a href="#array-cookies"> 2.7 Array Operator <code>new</code> Cookies </a></h3>
21122112

21132113
<p>
2114-
When operator <code>new</code> is used to create a new array,
2115-
a cookie is usually stored to remember the allocated length
2116-
(number of array elements)
2117-
so that it can be deallocated correctly.
2114+
When a <code>new</code> expression is used to create a new array,
2115+
a "cookie" must sometimes be added to the allocation. A cookie is
2116+
a header on the array allocation, preceding the array elements,
2117+
which stores the number of array elements that were allocated.
21182118

21192119
<p>
2120-
Specifically:
2120+
Let <code>T</code> be the element type of the allocated array,
2121+
looking through all levels of nested array.
2122+
Whether a cookie is required is determined as follows:
2123+
21212124
<ul>
2122-
<p>
2123-
<li> No cookie is required if the array element type T has a trivial
2124-
destructor (12.4 [class.dtor])
2125-
and the usual (array) deallocation function
2126-
(3.7.3.2 [basic.stc.dynamic.deallocation])
2127-
function does not take two arguments.
2125+
<li>No cookie is required if the selected allocation function
2126+
is the reserved placement allocation function
2127+
(that is, <code>::operator new[](size_t, void*)</code>).
21282128

2129-
<p>
2130-
(Note: if the usual array deallocation function takes two arguments,
2131-
then it is a member function whose second argument is of type size_t.
2132-
The standard guarantees (12.5 [class.free])
2133-
that this function will be passed the
2134-
number of bytes allocated with the previous array new expression.)
2129+
<li>Otherwise, a cookie is required if:
21352130

2136-
<p>
2137-
<li> No cookie is required if the <code>new</code> operator being used
2138-
is <code>::operator new[](size_t, void*)</code>.
2139-
2140-
<p>
2141-
<li> Otherwise, this ABI requires a cookie, setup as follows:
21422131
<ul>
2143-
<li> The cookie will have size <code>sizeof(size_t)</code>.
2144-
<li> Let <code>align</code> be the maximum alignment of
2145-
<code>size_t</code> and an element of the array to be allocated.
2146-
<li> Let <code>padding</code> be the maximum of
2147-
<code>sizeof(size_t)</code> and <code>align</code> bytes.
2148-
<li> The space allocated for the array will be the space required
2149-
by the array itself plus <code>padding</code> bytes.
2150-
<li> The alignment of the space allocated for the array will be
2151-
<code>align</code> bytes.
2152-
<li> The array data will begin at an offset of <code>align</code> bytes
2153-
from the space allocated for the array.
2154-
<li> The cookie will be stored in the <code>sizeof(size_t)</code> bytes
2155-
immediately preceding the array data.
2132+
<li><code>T</code> has a non-trivial destructor, or else
2133+
2134+
<li>there is an unambiguous usual array deallocation function
2135+
for <code>T</code> (as would be found for the <code>delete[]</code>
2136+
operator on an operand of type <code>T*</code>), and that
2137+
function takes a <code>size_t</code> argument.
2138+
2139+
<p>This operator must be looked up as if for a <code>delete[]</code>
2140+
without a <code>::</code> prefix, even if the <code>new</code>
2141+
expression does include a <code>::</code> prefix. This is
2142+
necessary to ensure consistency between <code>new</code>
2143+
and <code>delete</code>, as it is not always ill-defined
2144+
under the standard to mix the use of global and class-scoped
2145+
allocation and deallocation functions. (For example, a
2146+
class-scoped deallocation function might delegate to the
2147+
corresponding global deallocation function.)
2148+
</ul>
21562149
</ul>
21572150

2158-
<i>
2159-
<p>
2160-
These rules have the following consequences:
2161-
<ul>
2162-
<li> The array elements and the cookie are all aligned naturally.
2163-
<li> Padding will be required if <code>sizeof(size_t)</code>
2164-
is smaller than the array element alignment,
2165-
and if present will precede the cookie.
2166-
</ul>
2167-
</i>
2151+
<p>If a cookie is required, the allocation is adjusted as follows:
21682152

2153+
<ul>
2154+
<li>Let <code>cookie_t</code> be the type of a cookie. Under the
2155+
standard ABI, this is <code>size_t</code>; however, some platforms
2156+
use a variant ABI which stores additional information.
2157+
2158+
<li>Let <code>count</code> be the total number of objects of type
2159+
<code>T</code> that will be created, scaled appropriately by the
2160+
bounds of any nested arrays. This is the value that will be stored
2161+
in the cookie. For example, given the expresssion
2162+
<code>new T[len][7][5]</code>, <code>count</code> is
2163+
<code>len * 7 * 5</code>.
2164+
2165+
<li>Let <code>align</code> be <code>max(alignof(cookie_t), alignof(T))</code>.
2166+
This is the alignment of the allocation. Note that this is
2167+
a new-extended alignment if and only if <code>T</code> has a
2168+
new-extended alignment, and so the presence of a cookie does not
2169+
affect the choice of allocation or deallocation function.
2170+
2171+
<li>Let <code>prefix_size</code> be <code>max(sizeof(cookie_t), align)</code>.
2172+
2173+
<li>Let <code>allocation_size</code> be
2174+
<code>prefix_size + count * sizeof(T)</code>.
2175+
This is the size value that will be passed to the allocation
2176+
function.
2177+
2178+
<li>The first array element begins at offset <code>prefix_size</code>
2179+
from the start of the allocation. This pointer is the result of the
2180+
<code>new</code> expression.
2181+
2182+
<li>The cookie is stored at offset <code>prefix_size - sizeof(cookie_t)</code>
2183+
from the start of the allocation.
2184+
</ul>
21692185
</ul>
21702186

21712187
<p>
2172-
Given the above, the following is pseudocode for processing
2173-
<code>new(ARGS) T[n]</code>:
2174-
<code><pre>
2175-
if T has a trivial destructor (C++ standard, 12.4/3)
2176-
padding = 0
2177-
else if we're using ::operator new[](size_t, void*)
2178-
padding = 0
2179-
else
2180-
padding = max(sizeof(size_t), alignof(T))
2181-
2182-
p = operator new[](n * sizeof(T) + padding, ARGS)
2183-
p1 = (T*) ( (char *)p + padding )
2184-
2185-
if padding > 0
2186-
*( (size_t *)p1 - 1) = n
2187-
2188-
for i = [0, n)
2189-
create a T, using the default constructor, at p1[i]
2190-
2191-
return p1
2192-
</pre></code>
2188+
A <code>delete[]</code> expression must also compensate for the
2189+
possible presence of an array cookie:
21932190

2191+
<ul>
2192+
<li>First, the operand is converted to a pointer type as described
2193+
in the standard.
2194+
2195+
<li>Let <code>T</code> be the element type of the pointer,
2196+
looking through nested array types as above.
2197+
2198+
<li>Let <code>ptr</code> be the pointer (of type <code>T*</code>)
2199+
to the first array element.
2200+
2201+
<li>Whether a cookie is required is determined as if for a
2202+
non-<code>::</code>-prefixed, non-placement <code>new</code>
2203+
expression creating an array of type <code>T</code>. Note that
2204+
it is not possible to invoke the reserved placement deallocation
2205+
function (<code>::operator delete[](void*, void*)</code>) with
2206+
a <code>delete[]</code> expression, and so there is no need for
2207+
an exception for this case.
2208+
2209+
<li>If a cookie is required, it is found at offset
2210+
<code>-sizeof(cookie_t)</code> from <code>ptr</code>, and the
2211+
original allocation is found at offset <code>-prefix_size</code>
2212+
from <code>ptr</code>.
2213+
2214+
<li>If <code>T</code> has a non-trivial destructor, the value of
2215+
<code>count</code> stored in the cookie is the number of
2216+
elements to destroy.
2217+
2218+
<li>If the deallocation function has a <code>size_t</code> argument,
2219+
it is passed <code>allocation_size</code>, computed as above given the
2220+
value of <code>count</code> stored in the cookie.
2221+
</ul>
21942222

21952223

21962224
<p> <hr> <p>

0 commit comments

Comments
 (0)