Files
Chris Kennelly 767deb01c5 No public description
PiperOrigin-RevId: 757880659
Change-Id: Id86af8c3d606cc7ebfa87173eeb4a1f31240f8e2
2025-05-12 13:06:09 -07:00

251 lines
9.7 KiB
Markdown

# TCMalloc Basic Reference
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.
## C++ API
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 aligned `operator
new` function must be deallocated with an aligned `operator delete`.
### `::operator new` / `::operator new[]`
```
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`](https://abseil.io/docs/cpp/guides/base#abseil-exception-policy).
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.
### `::operator delete` / `::operator delete[]`
```
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.
### Extensions
We also expose a prototype of
[P0901](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p0901r5.html) in
https://github.com/google/tcmalloc/blob/master/tcmalloc/malloc_extension.h with
`__size_returning_new()`. This returns both memory and the size of the
allocation in bytes. It can be freed with `::operator delete`.
## C API
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](http://www.open-std.org/jtc1/sc22/wg14/www/docs/summary.htm#dr_445)
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](http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2293.htm), 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.
### `malloc()`
```
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.
### `calloc()`
```
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.
### `realloc()`
```
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.
### `aligned_alloc()`
```
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.)
### `posix_memalign()`
```
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.)
### `free()`
```
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.
### Extensions
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 by `malloc(size)`, subject to the alignment specified in
`flags`.
* `sdallocx(void* ptr, size_t size, int flags)` - Deallocates memory allocated
by `malloc` or `memalign`. It takes a size parameter to pass the original
allocation size, improving deallocation performance.