# 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 `` 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 `` 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.