Skip to main content

Include/pymem.h

cpython 3.14 @ ab2d84fe1023/Include/pymem.h

Include/pymem.h declares the public-facing memory API. It splits allocations into three domains: PyMem_ (object memory, GIL must be held), PyMem_Raw_ (raw C heap, no GIL requirement), and PyObject_ (object allocator, usually pymalloc). Each domain can be replaced independently with PyMem_SetAllocator.

Map

LinesSymbolRole
1-40PyMemAllocatorDomain, PyMemAllocatorExEnum and allocator struct for custom hooks
41-90PyMem_SetAllocator, PyMem_GetAllocatorAllocator injection/inspection API
91-120PyMem_Malloc, PyMem_Realloc, PyMem_FreeObject-domain allocator macros
121-145PyMem_RawMalloc, PyMem_RawCalloc, PyMem_RawFreeRaw-domain allocator functions

Reading

Three allocation domains

Domain prefixGIL requiredTypical backing
PyMem_Raw_Nomalloc
PyMem_Yespymalloc or malloc
PyObject_Yespymalloc

Pre-GIL or post-GIL code (signal handlers, finalizers before the interpreter is fully up) must use PyMem_Raw*. Using PyMem_* without holding the GIL is undefined behaviour.

PyMemAllocatorEx

// CPython: Include/pymem.h:44 PyMemAllocatorEx
typedef struct {
void *ctx;
void* (*malloc) (void *ctx, size_t size);
void* (*calloc) (void *ctx, size_t nelem, size_t elsize);
void* (*realloc)(void *ctx, void *ptr, size_t new_size);
void (*free) (void *ctx, void *ptr);
} PyMemAllocatorEx;

A custom allocator is injected per-domain via PyMem_SetAllocator(domain, &alloc). The ctx pointer is passed as the first argument to every callback, allowing stateful allocators (arena pools, leak trackers).

PyMem_Malloc on size 0

By contract PyMem_Malloc(0) returns a unique non-NULL pointer. Code that conditionally checks the return value for NULL to detect failure must also check size.

gopy notes

The Go runtime manages memory automatically. gopy does not expose PyMem_ APIs to user code; internally, Python object structs are allocated with new(T) or sync.Pool for hot paths. The PyMemAllocatorEx hook has no Go analogue.