TCMalloc provides implementations for C and C++ library memory management
routines (malloc()
, etc.) provided within the C and C++ standard libraries.
Currently, TCMalloc requires code that conforms to the C11 C standard library and the C++11, C++14, or C++17 C++ standard library.
NOTE: although the C API in this document is specific to the C language, the
entire TCMalloc API itself is designed to be callable directly within C++ code
(and we expect most usage to be from C++). The documentation in this section
assumes C constructs (e.g. size_t
) though invocations using equivalent C++
constructs of aliased types (e.g. std::size_t
) are instrinsically supported.
We implement the variants of operator new
and operator delete
from the
C++11, C++14, C++17 standards exposed within the <new>
header file. This
includes:
- The basic
::operator new()
,::operator delete()
, and array variant functions. - C++14's sized
::operator delete()
- C++17's overaligned
::operator new()
and::operator delete()
functions. As required by the C++ standard, memory allocated using an alignedoperator new
function must be deallocated with an alignedoperator delete
.
void* operator new(std::size_t count);
void* operator new(std::size_t count, const std::nothrow_t& tag) noexcept;
void* operator new(std::size_t count, std::align_val_t al); // C++17
void* operator new(std::size_t count,
std::align_val_t al, const std::nothrow_t&) noexcept; // C++17
void* operator new[](std::size_t count);
void* operator new[](std::size_t count, const std::nothrow_t& tag) noexcept;
void* operator new[](std::size_t count, std::align_val_t al); // C++17
void* operator new[](std::size_t count,
std::align_val_t al, const std::nothrow_t&) noexcept; // C++17
operator new
/operator new[]
allocates count
bytes. They may be invoked
directly but are more commonly invoked as part of a new-expression.
When __STDCPP_DEFAULT_NEW_ALIGNMENT__
is not specified (or is larger than 8
bytes), we use standard 16 byte alignments for ::operator new
without a
std::align_val_t
argument. However, for allocations under 16 bytes, we may
return an object with a lower alignment, as no object with a larger alignment
requirement can be allocated in the space. When compiled with
__STDCPP_DEFAULT_NEW_ALIGNMENT__ <= 8
, we use a set of sizes aligned to 8
bytes for raw storage allocated with ::operator new
.
NOTE: On many platforms, the value of __STDCPP_DEFAULT_NEW_ALIGNMENT__
can be
configured by the -fnew-alignment=...
flag.
The std::align_val_t
variants provide storage suitably aligned to the
requested alignment.
If the allocation is unsuccessful, a failure terminates the program.
NOTE: unlike in the C++ standard, we do not throw an exception in case of
allocation failure, or invoke std::get_new_handler()
repeatedly in an attempt
to successfully allocate, but instead crash directly. Such behavior can be used
as a performance optimization for move constructors not currently marked
noexcept
; such move operations can be allowed to fail directly due to
allocation failures. Within Abseil code, these direct allocation failures are
enabled with the Abseil build-time configuration macro
ABSL_ALLOCATOR_NOTHROW
.
If the std::no_throw_t
variant is utilized, upon failure, ::operator new
will return nullptr
instead.
The tcmalloc::hot_cold_t
variant accepts a hot_cold
hint for how frequently
an allocation would be accessed. It takes an 8-bit unsigned integer value, with
0
indicating that the allocation is rarely used and 255
indicating that the
allocation is accessed very frequently. TCMalloc may use these hints for better
data placement and locality.
void operator delete(void* ptr) noexcept;
void operator delete(void* ptr, std::size_t sz) noexcept;
void operator delete(void* ptr, std::align_val_t al) noexcept;
void operator delete(void* ptr, std::size_t sz,
std::align_val_t all) noexcept;
void operator delete[](void* ptr) noexcept;
void operator delete[](void* ptr, std::size_t sz) noexcept; // C++14
void operator delete[](void* ptr, std::align_val_t al) noexcept; // C++17
void operator delete[](void* ptr, std::size_t sz,
std::align_val_t al) noexcept; // C++17
::operator delete
/::operator delete[]
deallocate memory previously allocated
by a corresponding ::operator new
/::operator new[]
call respectively. It is
commonly invoked as part of a delete-expression.
Sized delete is used as a critical performance optimization, eliminating the need to perform a costly pointer-to-size lookup.
We also expose a prototype of
P0901 in
https://github.com/google/tcmalloc/blob/master/tcmalloc/malloc_extension.h with
tcmalloc_size_returning_operator_new()
. This returns both memory and the size
of the allocation in bytes. It can be freed with ::operator delete
.
The C standard library specifies the API for dynamic memory management within
the <stdlib.h>
header file. Implementations require C11 or greater.
TCMalloc provides implementation for the following C API functions:
malloc()
calloc()
realloc()
free()
aligned_alloc()
For malloc
, calloc
, and realloc
, we obey the behavior of C90 DR075 and
DR445
which states:
The alignment requirement still applies even if the size is too small for any object requiring the given alignment.
In other words, malloc(1)
returns alignof(std::max_align_t)
-aligned pointer.
Based on the progress of
N2293, we may relax
this alignment in the future.
Additionally, TCMalloc provides an implementation for the following POSIX standard library function, available within glibc:
posix_memalign()
TCMalloc also provides implementations for the following obsolete functions typically provided within libc implementations:
cfree()
memalign()
valloc()
pvalloc()
Documentation is not provided for these obsolete functions. The implementations are provided only for compatibility purposes.
void* malloc(size_t size);
malloc
allocates size
bytes of memory and returns a void *
pointer to the
start of that memory.
malloc(0)
returns a non-NULL zero-sized pointer. (Attempting to access memory
at this location is undefined.) If malloc()
fails for some reason, it returns
NULL.
void* calloc(size_t num, size_t size);
calloc()
allocates memory for an array of objects, zero-initializes all bytes
in allocated storage, and if allocation succeeds, returns a pointer to the first
byte in the allocated memory block.
calloc(num, 0)
or calloc(0, size)
returns a non-NULL zero-sized pointer.
(Attempting to access memory at this location is undefined.) If calloc()
fails
for some reason, it returns NULL.
void* realloc(void *ptr, size_t new_size);
realloc()
re-allocates memory for an existing region of memory by either
expanding or contracting the memory based on the passed new_size
in bytes,
returning a void*
pointer to the start of that memory (which may not change);
it does not perform any initialization of new areas of memory.
realloc(OBJ*, 0)
returns a NULL pointer. If realloc()
fails for some reason,
it also returns NULL.
void* aligned_alloc(size_t alignment, size_t size);
aligned_alloc()
allocates size
bytes of memory with alignment of size
alignment
and returns a void *
pointer to the start of that memory; it does
not perform any initialization.
The size
parameter must be an integral multiple of alignment
and alignment
must be a power of two. If either of these cases is not satisfied,
aligned_alloc()
will fail and return a NULL pointer.
aligned_alloc
with size=0
returns a non-NULL zero-sized pointer. (Attempting
to access memory at this location is undefined.)
int posix_memalign(void **memptr, size_t alignment, size_t size);
posix_memalign()
, like aligned_alloc()
allocates size
bytes of memory with
alignment of size alignment
to the start of memory pointed to by **memptr
;
it does not perform any initialization. This pointer can be cast to the desired
type of data pointer in order to be dereferenceable. If the alignment allocation
succeeds, posix_memalign()
returns 0
; otherwise it returns an error value.
posix_memalign
is similar to aligned_alloc()
but alignment
be a power of
two multiple of sizeof(void *)
. If the constraints are not satisfied,
posix_memalign()
will fail.
posix_memalign
with size=0
returns a non-NULL zero-sized pointer.
(Attempting to access memory at this location is undefined.)
void free(void* ptr);
free()
deallocates memory previously allocated by malloc()
, calloc()
,
aligned_alloc()
, posix_memalign()
, or realloc()
. If free()
is passed a
null pointer, the function does nothing.
These are contained in https://github.com/google/tcmalloc/blob/master/tcmalloc/malloc_extension.h.
nallocx(size_t size, int flags)
- Returns the number of bytes that would be allocated bymalloc(size)
, subject to the alignment specified inflags
.sdallocx(void* ptr, size_t size, int flags)
- Deallocates memory allocated bymalloc
ormemalign
. It takes a size parameter to pass the original allocation size, improving deallocation performance.