[support.dynamic] (original) (raw)

17 Language support library [support]

17.6 Dynamic memory management [support.dynamic]

17.6.1 General [support.dynamic.general]

The header defines several functions that manage the allocation of dynamic storage in a program.

It also defines components for reporting storage management errors.

17.6.2 Header synopsis [new.syn]

namespace std { class bad_alloc;class bad_array_new_length;struct destroying_delete_t { explicit destroying_delete_t() = default;};inline constexpr destroying_delete_t destroying_delete{};enum class align_val_t : size_t {};struct nothrow_t { explicit nothrow_t() = default; };extern const nothrow_t nothrow;using new_handler = void (*)(); new_handler get_new_handler() noexcept; new_handler set_new_handler(new_handler new_p) noexcept;template<class T> constexpr T* launder(T* p) noexcept;inline constexpr size_t hardware_destructive_interference_size = implementation-defined;inline constexpr size_t hardware_constructive_interference_size = implementation-defined;} void* operator new(std::size_t size);void* operator new(std::size_t size, std::align_val_t alignment);void* operator new(std::size_t size, const std::nothrow_t&) noexcept;void* operator new(std::size_t size, std::align_val_t alignment, const std::nothrow_t&) noexcept;void operator delete(void* ptr) noexcept;void operator delete(void* ptr, std::size_t size) noexcept;void operator delete(void* ptr, std::align_val_t alignment) noexcept;void operator delete(void* ptr, std::size_t size, std::align_val_t alignment) noexcept;void operator delete(void* ptr, const std::nothrow_t&) noexcept;void operator delete(void* ptr, std::align_val_t alignment, const std::nothrow_t&) noexcept;void* operator new[](std::size_t size);void* operator new[](std::size_t size, std::align_val_t alignment);void* operator new[](std::size_t size, const std::nothrow_t&) noexcept;void* operator new[](std::size_t size, std::align_val_t alignment,const std::nothrow_t&) noexcept;void operator delete[](void* ptr) noexcept;void operator delete[](void* ptr, std::size_t size) noexcept;void operator delete[](void* ptr, std::align_val_t alignment) noexcept;void operator delete[](void* ptr, std::size_t size, std::align_val_t alignment) noexcept;void operator delete[](void* ptr, const std::nothrow_t&) noexcept;void operator delete[](void* ptr, std::align_val_t alignment, const std::nothrow_t&) noexcept;constexpr void* operator new (std::size_t size, void* ptr) noexcept;constexpr void* operator new[](std::size_t size, void* ptr) noexcept;void operator delete (void* ptr, void*) noexcept;void operator delete[](void* ptr, void*) noexcept;

17.6.3 Storage allocation and deallocation [new.delete]

17.6.3.1 General [new.delete.general]

Except where otherwise specified, the provisions of [basic.stc.dynamic]apply to the library versions of operator new and operator delete.

If the value of an alignment argument passed to any of these functions is not a valid alignment value, the behavior is undefined.

On freestanding implementations, it is implementation-defined whether the default versions of the replaceable global allocation functions satisfy the required behaviors described in [new.delete.single] and [new.delete.array].

[Note 1:

A freestanding implementation's default versions of the replaceable global allocation functions can cause undefined behavior when invoked.

During constant evaluation, the behaviors of those default versions are irrelevant, as those calls are omitted ([expr.new]).

— _end note_]

Recommended practice: If any of the default versions of the replaceable global allocation functions meet the requirements of a hosted implementation, they all should.

17.6.3.2 Single-object forms [new.delete.single]

void* operator new(std::size_t size);void* operator new(std::size_t size, std::align_val_t alignment);

The second form is called for a type with new-extended alignment, and the first form is called otherwise.

Required behavior: Return a non-null pointer to suitably aligned storage ([basic.stc.dynamic]), or else throw abad_alloc exception.

This requirement is binding on any replacement versions of these functions.

Default behavior:

void* operator new(std::size_t size, const std::nothrow_t&) noexcept;void* operator new(std::size_t size, std::align_val_t alignment, const std::nothrow_t&) noexcept;

Effects: Same as above, except that these are called by a placement version of anew-expressionwhen a C++ program prefers a null pointer result as an error indication, instead of abad_allocexception.

Required behavior: Return a non-null pointer to suitably aligned storage ([basic.stc.dynamic]), or else return a null pointer.

Each of these nothrow versions ofoperator newreturns a pointer obtained as if acquired from the (possibly replaced) corresponding non-placement function.

This requirement is binding on any replacement versions of these functions.

Default behavior: Calls operator new(size), or operator new(size, alignment), respectively.

If the call returns normally, returns the result of that call.

Otherwise, returns a null pointer.

[Example 1: T* p1 = new T; T* p2 = new(nothrow) T; — _end example_]

void operator delete(void* ptr) noexcept;void operator delete(void* ptr, std::size_t size) noexcept;void operator delete(void* ptr, std::align_val_t alignment) noexcept;void operator delete(void* ptr, std::size_t size, std::align_val_t alignment) noexcept;

Preconditions: ptr is a null pointer or its value represents the address of a block of memory allocated by an earlier call to a (possibly replaced)operator new(std​::​size_t)oroperator new(std​::​size_t, std​::​align_val_t)which has not been invalidated by an intervening call tooperator delete.

If the alignment parameter is not present,ptr was returned by an allocation function without an alignment parameter.

If present, the alignment argument is equal to the alignment argument passed to the allocation function that returned ptr.

If present, the size argument is equal to the size argument passed to the allocation function that returned ptr.

Required behavior: A call to an operator deletewith a size parameter may be changed to a call to the corresponding operator deletewithout a size parameter, without affecting memory allocation.

[Note 1:

A conforming implementation is foroperator delete(void* ptr, std​::​size_t size) to simply calloperator delete(ptr).

— _end note_]

Default behavior: The functions that have a size parameter forward their other parameters to the corresponding function without a size parameter.

[Note 2:

See the note in the below Remarks: paragraph.

— _end note_]

Default behavior: If ptr is null, does nothing.

Otherwise, reclaims the storage allocated by the earlier call to operator new.

Remarks: It is unspecified under what conditions part or all of suchreclaimed storage will be allocated by subsequent calls tooperator newor any ofaligned_alloc,calloc,malloc, orrealloc, declared in .

If a replacement function without a size parameter is defined by the program, the program should also define the corresponding function with a size parameter.

If a replacement function with a size parameter is defined by the program, the program shall also define the corresponding version without the size parameter.

[Note 3:

The default behavior above might change in the future, which will require replacing both deallocation functions when replacing the allocation function.

— _end note_]

void operator delete(void* ptr, const std::nothrow_t&) noexcept;void operator delete(void* ptr, std::align_val_t alignment, const std::nothrow_t&) noexcept;

Preconditions: ptr is a null pointer or its value represents the address of a block of memory allocated by an earlier call to a (possibly replaced)operator new(std​::​size_t)oroperator new(std​::​size_t, std​::​align_val_t)which has not been invalidated by an intervening call tooperator delete.

If the alignment parameter is not present,ptr was returned by an allocation function without an alignment parameter.

If present, the alignment argument is equal to the alignment argument passed to the allocation function that returned ptr.

Effects: The deallocation functions ([basic.stc.dynamic.deallocation]) called by the implementation to render the value of ptr invalid when the constructor invoked from a nothrow placement version of the new-expression throws an exception.

Default behavior: Calls operator delete(ptr), or operator delete(ptr, alignment), respectively.

17.6.3.3 Array forms [new.delete.array]

void* operator new[](std::size_t size);void* operator new[](std::size_t size, std::align_val_t alignment);

The second form is called for a type with new-extended alignment, and the first form is called otherwise.189

Required behavior: Same as for the corresponding single-object forms.

This requirement is binding on any replacement versions of these functions.

Default behavior: Returnsoperator new(size), oroperator new(size, alignment), respectively.

void* operator new[](std::size_t size, const std::nothrow_t&) noexcept;void* operator new[](std::size_t size, std::align_val_t alignment, const std::nothrow_t&) noexcept;

Effects: Same as above, except that these are called by a placement version of anew-expressionwhen a C++ program prefers a null pointer result as an error indication, instead of abad_allocexception.

Required behavior: Return a non-null pointer to suitably aligned storage ([basic.stc.dynamic]), or else return a null pointer.

Each of these nothrow versions ofoperator new[]returns a pointer obtained as if acquired from the (possibly replaced) corresponding non-placement function.

This requirement is binding on any replacement versions of these functions.

Default behavior: Calls operator new[](size), or operator new[](size, alignment), respectively.

If the call returns normally, returns the result of that call.

Otherwise, returns a null pointer.

void operator delete[](void* ptr) noexcept;void operator delete[](void* ptr, std::size_t size) noexcept;void operator delete[](void* ptr, std::align_val_t alignment) noexcept;void operator delete[](void* ptr, std::size_t size, std::align_val_t alignment) noexcept;

Preconditions: ptr is a null pointer or its value represents the address of a block of memory allocated by an earlier call to a (possibly replaced)operator new[](std​::​size_t)oroperator new[](std​::​size_t, std​::​align_val_t)which has not been invalidated by an intervening call tooperator delete[].

If the alignment parameter is not present,ptr was returned by an allocation function without an alignment parameter.

If present, the alignment argument is equal to the alignment argument passed to the allocation function that returned ptr.

If present, the size argument is equal to the size argument passed to the allocation function that returned ptr.

Required behavior: A call to an operator delete[]with a size parameter may be changed to a call to the corresponding operator delete[]without a size parameter, without affecting memory allocation.

[Note 1:

A conforming implementation is foroperator delete[](void* ptr, std​::​size_t size) to simply calloperator delete[](ptr).

— _end note_]

Default behavior: The functions that have a size parameter forward their other parameters to the corresponding function without a size parameter.

The functions that do not have a size parameter forward their parameters to the corresponding operator delete (single-object) function.

If a replacement function without a size parameter is defined by the program, the program should also define the corresponding function with a size parameter.

If a replacement function with a size parameter is defined by the program, the program shall also define the corresponding version without the size parameter.

[Note 2:

The default behavior above might change in the future, which will require replacing both deallocation functions when replacing the allocation function.

— _end note_]

void operator delete[](void* ptr, const std::nothrow_t&) noexcept;void operator delete[](void* ptr, std::align_val_t alignment, const std::nothrow_t&) noexcept;

Preconditions: ptr is a null pointer or its value represents the address of a block of memory allocated by an earlier call to a (possibly replaced)operator new[](std​::​size_t)oroperator new[](std​::​size_t, std​::​align_val_t)which has not been invalidated by an intervening call tooperator delete[].

If the alignment parameter is not present,ptr was returned by an allocation function without an alignment parameter.

If present, the alignment argument is equal to the alignment argument passed to the allocation function that returned ptr.

Effects: The deallocation functions ([basic.stc.dynamic.deallocation]) called by the implementation to render the value of ptr invalid when the constructor invoked from a nothrow placement version of the array new-expression throws an exception.

Default behavior: Calls operator delete[](ptr), or operator delete[](ptr, alignment), respectively.

17.6.3.4 Non-allocating forms [new.delete.placement]

These functions are reserved; a C++ program may not define functions that displace the versions in the C++ standard library ([constraints]).

The provisions of [basic.stc.dynamic] do not apply to these reserved placement forms of operator new and operator delete.

constexpr void* operator new(std::size_t size, void* ptr) noexcept;

Remarks: Intentionally performs no other action.

[Example 1:

This can be useful for constructing an object at a known address:void* place = operator new(sizeof(Something)); Something* p = new (place) Something();

— _end example_]

constexpr void* operator new[](std::size_t size, void* ptr) noexcept;

Remarks: Intentionally performs no other action.

void operator delete(void* ptr, void*) noexcept;

Effects: Intentionally performs no action.

Remarks: Default function called when any part of the initialization in a placement new-expression that invokes the library's non-array placement operator new terminates by throwing an exception ([expr.new]).

void operator delete[](void* ptr, void*) noexcept;

Effects: Intentionally performs no action.

Remarks: Default function called when any part of the initialization in a placement new-expression that invokes the library's array placement operator new terminates by throwing an exception ([expr.new]).

17.6.3.5 Data races [new.delete.dataraces]

For purposes of determining the existence of data races, the library versions of operator new, user replacement versions of global operator new, the C standard library functionsaligned_alloc, calloc, and malloc, the library versions of operator delete, user replacement versions of operator delete, the C standard library functionfree, and the C standard library function realloc shall not introduce a data race ([res.on.data.races]).

Calls to these functions that allocate or deallocate a particular unit of storage shall occur in a single total order, and each such deallocation call shall happen beforethe next allocation (if any) in this order.

17.6.4 Storage allocation errors [alloc.errors]

17.6.4.1 Class bad_alloc [bad.alloc]

namespace std { class bad_alloc : public exception { public: constexpr const char* what() const noexcept override;};}

The classbad_allocdefines the type of objects thrown as exceptions by the implementation to report a failure to allocate storage.

constexpr const char* what() const noexcept override;

Returns: An implementation-defined ntbs.

17.6.4.2 Class bad_array_new_length [new.badlength]

namespace std { class bad_array_new_length : public bad_alloc { public: constexpr const char* what() const noexcept override;};}

The class bad_array_new_length defines the type of objects thrown as exceptions by the implementation to report an attempt to allocate an array of size less than zero or greater than an implementation-defined limit ([expr.new]).

constexpr const char* what() const noexcept override;

Returns: An implementation-defined ntbs.

17.6.4.3 Type new_handler [new.handler]

using new_handler = void (*)();

The type of ahandler functionto be called byoperator new()oroperator new[]() ([new.delete]) when they cannot satisfy a request for additional storage.

Required behavior: A new_handler shall perform one of the following:

17.6.4.4 set_new_handler [set.new.handler]

new_handler set_new_handler(new_handler new_p) noexcept;

Effects: Establishes the function designated by new_p as the currentnew_handler.

Returns: The previous new_handler.

Remarks: The initial new_handler is a null pointer.

17.6.4.5 get_new_handler [get.new.handler]

new_handler get_new_handler() noexcept;

Returns: The current new_handler.

[Note 1:

This can be a null pointer value.

— _end note_]

17.6.5 Pointer optimization barrier [ptr.launder]

template<class T> constexpr T* launder(T* p) noexcept;

Mandates: !is_function_v<T> && !is_void_v<T> is true.

Preconditions: p represents the address A of a byte in memory.

An object X that is within its lifetimeand whose type is similar to Tis located at the address A.

All bytes of storage that would be reachable through ([basic.compound]) the result are reachable through p.

Returns: A value of type T* that points to X.

Remarks: An invocation of this function may be used in a core constant expression if and only if the (converted) value of its argument may be used in place of the function invocation.

[Note 1:

If a new object is created in storage occupied by an existing object of the same type, a pointer to the original object can be used to refer to the new object unless its complete object is a const object or it is a base class subobject; in the latter cases, this function can be used to obtain a usable pointer to the new object.

— _end note_]

[Example 1: struct X { int n; };const X *p = new const X{3};const int a = p->n;new (const_cast<X*>(p)) const X{5}; const int b = p->n; const int c = std::launder(p)->n; — _end example_]

17.6.6 Hardware interference size [hardware.interference]

inline constexpr size_t hardware_destructive_interference_size = _implementation-defined_;

This number is the minimum recommended offset between two concurrently-accessed objects to avoid additional performance degradation due to contention introduced by the implementation.

It shall be at least alignof(max_align_t).

[Example 1: struct keep_apart { alignas(hardware_destructive_interference_size) atomic<int> cat;alignas(hardware_destructive_interference_size) atomic<int> dog;}; — _end example_]

inline constexpr size_t hardware_constructive_interference_size = _implementation-defined_;

This number is the maximum recommended size of contiguous memory occupied by two objects accessed with temporal locality by concurrent threads.

It shall be at least alignof(max_align_t).

[Example 2: struct together { atomic<int> dog;int puppy;};struct kennel { alignas(sizeof(together)) together pack;};static_assert(sizeof(together) <= hardware_constructive_interference_size); — _end example_]