diff --git a/abi.html b/abi.html index 2e8dd75..b9eb5ab 100644 --- a/abi.html +++ b/abi.html @@ -2111,86 +2111,114 @@
new
Cookies
-When operator new
is used to create a new array,
-a cookie is usually stored to remember the allocated length
-(number of array elements)
-so that it can be deallocated correctly.
+When a new
expression is used to create a new array,
+a "cookie" must sometimes be added to the allocation. A cookie is
+a header on the array allocation, preceding the array elements,
+which stores the number of array elements that were allocated.
-Specifically:
+Let T
be the element type of the allocated array,
+looking through all levels of nested array.
+Whether a cookie is required is determined as follows:
+
-
::operator new[](size_t, void*)
).
- - (Note: if the usual array deallocation function takes two arguments, - then it is a member function whose second argument is of type size_t. - The standard guarantees (12.5 [class.free]) - that this function will be passed the - number of bytes allocated with the previous array new expression.) +
-
new
operator being used
- is ::operator new[](size_t, void*)
.
-
--
sizeof(size_t)
.
- align
be the maximum alignment of
- size_t
and an element of the array to be allocated.
- padding
be the maximum of
- sizeof(size_t)
and align
bytes.
- padding
bytes.
- align
bytes.
- align
bytes
- from the space allocated for the array.
- sizeof(size_t)
bytes
- immediately preceding the array data.
+ T
has a non-trivial destructor, or else
+
+ T
(as would be found for the delete[]
+ operator on an operand of type T*
), and that
+ function takes a size_t
argument.
+
+ This operator must be looked up as if for a delete[]
+ without a ::
prefix, even if the new
+ expression does include a ::
prefix. This is
+ necessary to ensure consistency between new
+ and delete
, as it is not always ill-defined
+ under the standard to mix the use of global and class-scoped
+ allocation and deallocation functions. (For example, a
+ class-scoped deallocation function might delegate to the
+ corresponding global deallocation function.)
+
- These rules have the following consequences: -
sizeof(size_t)
- is smaller than the array element alignment,
- and if present will precede the cookie.
- If a cookie is required, the allocation is adjusted as follows: +
cookie_t
be the type of a cookie. Under the
+ standard ABI, this is size_t
; however, some platforms
+ use a variant ABI which stores additional information.
+
+ count
be the total number of objects of type
+ T
that will be created, scaled appropriately by the
+ bounds of any nested arrays. This is the value that will be stored
+ in the cookie. For example, given the expresssion
+ new T[len][7][5]
, count
is
+ len * 7 * 5
.
+
+ align
be max(alignof(cookie_t), alignof(T))
.
+ This is the alignment of the allocation. Note that this is
+ a new-extended alignment if and only if T
has a
+ new-extended alignment, and so the presence of a cookie does not
+ affect the choice of allocation or deallocation function.
+
+ prefix_size
be max(sizeof(cookie_t), align)
.
+
+ allocation_size
be
+ prefix_size + count * sizeof(T)
.
+ This is the size value that will be passed to the allocation
+ function.
+
+ prefix_size
+ from the start of the allocation. This pointer is the result of the
+ new
expression.
+
+ prefix_size - sizeof(cookie_t)
+ from the start of the allocation.
+
-Given the above, the following is pseudocode for processing
-new(ARGS) T[n]
:
-
+A
- if T has a trivial destructor (C++ standard, 12.4/3)
- padding = 0
- else if we're using ::operator new[](size_t, void*)
- padding = 0
- else
- padding = max(sizeof(size_t), alignof(T))
-
- p = operator new[](n * sizeof(T) + padding, ARGS)
- p1 = (T*) ( (char *)p + padding )
-
- if padding > 0
- *( (size_t *)p1 - 1) = n
-
- for i = [0, n)
- create a T, using the default constructor, at p1[i]
-
- return p1
-
delete[]
expression must also compensate for the
+possible presence of an array cookie:
+
T
be the element type of the pointer,
+ looking through nested array types as above.
+
+ptr
be the pointer (of type T*
)
+ to the first array element.
+
+::
-prefixed, non-placement new
+ expression creating an array of type T
. Note that
+ it is not possible to invoke the reserved placement deallocation
+ function (::operator delete[](void*, void*)
) with
+ a delete[]
expression, and so there is no need for
+ an exception for this case.
+
+-sizeof(cookie_t)
from ptr
, and the
+ original allocation is found at offset -prefix_size
+ from ptr
.
+
+T
has a non-trivial destructor, the value of
+ count
stored in the cookie is the number of
+ elements to destroy.
+
+size_t
argument,
+ it is passed allocation_size
, computed as above given the
+ value of count
stored in the cookie.
+