Memory Management

Overview

Memory management in Python involves a private heap containing all Pythonobjects and data structures. The management of this private heap is ensuredinternally by thePython memory manager. The Python memory manager hasdifferent components which deal with various dynamic storage management aspects,like sharing, segmentation, preallocation or caching.

At the lowest level, a raw memory allocator ensures that there is enough room inthe private heap for storing all Python-related data by interacting with thememory manager of the operating system. On top of the raw memory allocator,several object-specific allocators operate on the same heap and implementdistinct memory management policies adapted to the peculiarities of every objecttype. For example, integer objects are managed differently within the heap thanstrings, tuples or dictionaries because integers imply different storagerequirements and speed/space tradeoffs. The Python memory manager thus delegatessome of the work to the object-specific allocators, but ensures that the latteroperate within the bounds of the private heap.

It is important to understand that the management of the Python heap isperformed by the interpreter itself and that the user has no control over it,even if they regularly manipulate object pointers to memory blocks inside thatheap. The allocation of heap space for Python objects and other internalbuffers is performed on demand by the Python memory manager through the Python/CAPI functions listed in this document.

To avoid memory corruption, extension writers should never try to operate onPython objects with the functions exported by the C library:malloc(),calloc(),realloc() andfree(). This will result in mixedcalls between the C allocator and the Python memory manager with fatalconsequences, because they implement different algorithms and operate ondifferent heaps. However, one may safely allocate and release memory blockswith the C library allocator for individual purposes, as shown in the followingexample:

PyObject*res;char*buf=(char*)malloc(BUFSIZ);/* for I/O */if(buf==NULL)returnPyErr_NoMemory();...DosomeI/Ooperationinvolvingbuf...res=PyBytes_FromString(buf);free(buf);/* malloc'ed */returnres;

In this example, the memory request for the I/O buffer is handled by the Clibrary allocator. The Python memory manager is involved only in the allocationof the bytes object returned as a result.

In most situations, however, it is recommended to allocate memory from thePython heap specifically because the latter is under control of the Pythonmemory manager. For example, this is required when the interpreter is extendedwith new object types written in C. Another reason for using the Python heap isthe desire toinform the Python memory manager about the memory needs of theextension module. Even when the requested memory is used exclusively forinternal, highly specific purposes, delegating all memory requests to the Pythonmemory manager causes the interpreter to have a more accurate image of itsmemory footprint as a whole. Consequently, under certain circumstances, thePython memory manager may or may not trigger appropriate actions, like garbagecollection, memory compaction or other preventive procedures. Note that by usingthe C library allocator as shown in the previous example, the allocated memoryfor the I/O buffer escapes completely the Python memory manager.

See also

ThePYTHONMALLOC environment variable can be used to configurethe memory allocators used by Python.

ThePYTHONMALLOCSTATS environment variable can be used to printstatistics of thepymalloc memory allocator every time anew pymalloc object arena is created, and on shutdown.

Allocator Domains

All allocating functions belong to one of three different “domains” (see alsoPyMemAllocatorDomain). These domains represent different allocationstrategies and are optimized for different purposes. The specific details onhow every domain allocates memory or what internal functions each domain callsis considered an implementation detail, but for debugging purposes a simplifiedtable can be found athere.The APIs used to allocate and free a block of memory must be from the same domain.For example,PyMem_Free() must be used to free memory allocated usingPyMem_Malloc().

The three allocation domains are:

  • Raw domain: intended for allocating memory for general-purpose memorybuffers where the allocationmust go to the system allocator or where theallocator can operate without theGIL. The memory is requested directlyfrom the system. SeeRaw Memory Interface.

  • “Mem” domain: intended for allocating memory for Python buffers andgeneral-purpose memory buffers where the allocation must be performed withtheGIL held. The memory is taken from the Python private heap.SeeMemory Interface.

  • Object domain: intended for allocating memory for Python objects. Thememory is taken from the Python private heap. SeeObject allocators.

Note

Thefree-threaded build requires that only Python objects are allocated using the “object” domainand that all Python objects are allocated using that domain. This differs from the prior Python versions,where this was only a best practice and not a hard requirement.

For example, buffers (non-Python objects) should be allocated usingPyMem_Malloc(),PyMem_RawMalloc(), ormalloc(), but notPyObject_Malloc().

SeeMemory Allocation APIs.

Raw Memory Interface

The following function sets are wrappers to the system allocator. Thesefunctions are thread-safe, theGIL does notneed to be held.

Thedefault raw memory allocator usesthe following functions:malloc(),calloc(),realloc()andfree(); callmalloc(1) (orcalloc(1,1)) when requestingzero bytes.

Added in version 3.4.

void*PyMem_RawMalloc(size_tn)
Part of theStable ABI since version 3.13.

Allocatesn bytes and returns a pointer of typevoid* to theallocated memory, orNULL if the request fails.

Requesting zero bytes returns a distinct non-NULL pointer if possible, asifPyMem_RawMalloc(1) had been called instead. The memory will not havebeen initialized in any way.

void*PyMem_RawCalloc(size_tnelem,size_telsize)
Part of theStable ABI since version 3.13.

Allocatesnelem elements each whose size in bytes iselsize and returnsa pointer of typevoid* to the allocated memory, orNULL if therequest fails. The memory is initialized to zeros.

Requesting zero elements or elements of size zero bytes returns a distinctnon-NULL pointer if possible, as ifPyMem_RawCalloc(1,1) had beencalled instead.

Added in version 3.5.

void*PyMem_RawRealloc(void*p,size_tn)
Part of theStable ABI since version 3.13.

Resizes the memory block pointed to byp ton bytes. The contents willbe unchanged to the minimum of the old and the new sizes.

Ifp isNULL, the call is equivalent toPyMem_RawMalloc(n); else ifn is equal to zero, the memory block is resized but is not freed, and thereturned pointer is non-NULL.

Unlessp isNULL, it must have been returned by a previous call toPyMem_RawMalloc(),PyMem_RawRealloc() orPyMem_RawCalloc().

If the request fails,PyMem_RawRealloc() returnsNULL andpremains a valid pointer to the previous memory area.

voidPyMem_RawFree(void*p)
Part of theStable ABI since version 3.13.

Frees the memory block pointed to byp, which must have been returned by aprevious call toPyMem_RawMalloc(),PyMem_RawRealloc() orPyMem_RawCalloc(). Otherwise, or ifPyMem_RawFree(p) has beencalled before, undefined behavior occurs.

Ifp isNULL, no operation is performed.

Memory Interface

The following function sets, modeled after the ANSI C standard, but specifyingbehavior when requesting zero bytes, are available for allocating and releasingmemory from the Python heap.

Thedefault memory allocator uses thepymalloc memory allocator.

Warning

TheGIL must be held when using thesefunctions.

Changed in version 3.6:The default allocator is now pymalloc instead of systemmalloc().

void*PyMem_Malloc(size_tn)
Part of theStable ABI.

Allocatesn bytes and returns a pointer of typevoid* to theallocated memory, orNULL if the request fails.

Requesting zero bytes returns a distinct non-NULL pointer if possible, asifPyMem_Malloc(1) had been called instead. The memory will not havebeen initialized in any way.

void*PyMem_Calloc(size_tnelem,size_telsize)
Part of theStable ABI since version 3.7.

Allocatesnelem elements each whose size in bytes iselsize and returnsa pointer of typevoid* to the allocated memory, orNULL if therequest fails. The memory is initialized to zeros.

Requesting zero elements or elements of size zero bytes returns a distinctnon-NULL pointer if possible, as ifPyMem_Calloc(1,1) had been calledinstead.

Added in version 3.5.

void*PyMem_Realloc(void*p,size_tn)
Part of theStable ABI.

Resizes the memory block pointed to byp ton bytes. The contents will beunchanged to the minimum of the old and the new sizes.

Ifp isNULL, the call is equivalent toPyMem_Malloc(n); else ifnis equal to zero, the memory block is resized but is not freed, and thereturned pointer is non-NULL.

Unlessp isNULL, it must have been returned by a previous call toPyMem_Malloc(),PyMem_Realloc() orPyMem_Calloc().

If the request fails,PyMem_Realloc() returnsNULL andp remainsa valid pointer to the previous memory area.

voidPyMem_Free(void*p)
Part of theStable ABI.

Frees the memory block pointed to byp, which must have been returned by aprevious call toPyMem_Malloc(),PyMem_Realloc() orPyMem_Calloc(). Otherwise, or ifPyMem_Free(p) has been calledbefore, undefined behavior occurs.

Ifp isNULL, no operation is performed.

The following type-oriented macros are provided for convenience. Note thatTYPE refers to any C type.

PyMem_New(TYPE,n)

Same asPyMem_Malloc(), but allocates(n*sizeof(TYPE)) bytes ofmemory. Returns a pointer cast toTYPE*. The memory will not havebeen initialized in any way.

PyMem_Resize(p,TYPE,n)

Same asPyMem_Realloc(), but the memory block is resized to(n*sizeof(TYPE)) bytes. Returns a pointer cast toTYPE*. On return,p will be a pointer to the new memory area, orNULL in the event offailure.

This is a C preprocessor macro;p is always reassigned. Save the originalvalue ofp to avoid losing memory when handling errors.

voidPyMem_Del(void*p)

Same asPyMem_Free().

In addition, the following macro sets are provided for calling the Python memoryallocator directly, without involving the C API functions listed above. However,note that their use does not preserve binary compatibility across Pythonversions and is therefore deprecated in extension modules.

  • PyMem_MALLOC(size)

  • PyMem_NEW(type,size)

  • PyMem_REALLOC(ptr,size)

  • PyMem_RESIZE(ptr,type,size)

  • PyMem_FREE(ptr)

  • PyMem_DEL(ptr)

Object allocators

The following function sets, modeled after the ANSI C standard, but specifyingbehavior when requesting zero bytes, are available for allocating and releasingmemory from the Python heap.

Note

There is no guarantee that the memory returned by these allocators can besuccessfully cast to a Python object when intercepting the allocatingfunctions in this domain by the methods described intheCustomize Memory Allocators section.

Thedefault object allocator uses thepymalloc memory allocator.

Warning

TheGIL must be held when using thesefunctions.

void*PyObject_Malloc(size_tn)
Part of theStable ABI.

Allocatesn bytes and returns a pointer of typevoid* to theallocated memory, orNULL if the request fails.

Requesting zero bytes returns a distinct non-NULL pointer if possible, asifPyObject_Malloc(1) had been called instead. The memory will not havebeen initialized in any way.

void*PyObject_Calloc(size_tnelem,size_telsize)
Part of theStable ABI since version 3.7.

Allocatesnelem elements each whose size in bytes iselsize and returnsa pointer of typevoid* to the allocated memory, orNULL if therequest fails. The memory is initialized to zeros.

Requesting zero elements or elements of size zero bytes returns a distinctnon-NULL pointer if possible, as ifPyObject_Calloc(1,1) had been calledinstead.

Added in version 3.5.

void*PyObject_Realloc(void*p,size_tn)
Part of theStable ABI.

Resizes the memory block pointed to byp ton bytes. The contents will beunchanged to the minimum of the old and the new sizes.

Ifp isNULL, the call is equivalent toPyObject_Malloc(n); else ifnis equal to zero, the memory block is resized but is not freed, and thereturned pointer is non-NULL.

Unlessp isNULL, it must have been returned by a previous call toPyObject_Malloc(),PyObject_Realloc() orPyObject_Calloc().

If the request fails,PyObject_Realloc() returnsNULL andp remainsa valid pointer to the previous memory area.

voidPyObject_Free(void*p)
Part of theStable ABI.

Frees the memory block pointed to byp, which must have been returned by aprevious call toPyObject_Malloc(),PyObject_Realloc() orPyObject_Calloc(). Otherwise, or ifPyObject_Free(p) has been calledbefore, undefined behavior occurs.

Ifp isNULL, no operation is performed.

Default Memory Allocators

Default memory allocators:

Configuration

Name

PyMem_RawMalloc

PyMem_Malloc

PyObject_Malloc

Release build

"pymalloc"

malloc

pymalloc

pymalloc

Debug build

"pymalloc_debug"

malloc + debug

pymalloc + debug

pymalloc + debug

Release build, without pymalloc

"malloc"

malloc

malloc

malloc

Debug build, without pymalloc

"malloc_debug"

malloc + debug

malloc + debug

malloc + debug

Legend:

Customize Memory Allocators

Added in version 3.4.

typePyMemAllocatorEx

Structure used to describe a memory block allocator. The structure hasthe following fields:

Field

Meaning

void*ctx

user context passed as first argument

void*malloc(void*ctx,size_tsize)

allocate a memory block

void*calloc(void*ctx,size_tnelem,size_telsize)

allocate a memory block initializedwith zeros

void*realloc(void*ctx,void*ptr,size_tnew_size)

allocate or resize a memory block

voidfree(void*ctx,void*ptr)

free a memory block

Changed in version 3.5:ThePyMemAllocator structure was renamed toPyMemAllocatorEx and a newcalloc field was added.

typePyMemAllocatorDomain

Enum used to identify an allocator domain. Domains:

PYMEM_DOMAIN_RAW

Functions:

PYMEM_DOMAIN_MEM

Functions:

PYMEM_DOMAIN_OBJ

Functions:

voidPyMem_GetAllocator(PyMemAllocatorDomaindomain,PyMemAllocatorEx*allocator)

Get the memory block allocator of the specified domain.

voidPyMem_SetAllocator(PyMemAllocatorDomaindomain,PyMemAllocatorEx*allocator)

Set the memory block allocator of the specified domain.

The new allocator must return a distinct non-NULL pointer when requestingzero bytes.

For thePYMEM_DOMAIN_RAW domain, the allocator must bethread-safe: theGIL is not held when theallocator is called.

For the remaining domains, the allocator must also be thread-safe:the allocator may be called in different interpreters that do notshare aGIL.

If the new allocator is not a hook (does not call the previous allocator),thePyMem_SetupDebugHooks() function must be called to reinstall thedebug hooks on top on the new allocator.

See alsoPyPreConfig.allocator andPreinitialize Pythonwith PyPreConfig.

Warning

PyMem_SetAllocator() does have the following contract:

  • It can be called afterPy_PreInitialize() and beforePy_InitializeFromConfig() to install a custom memoryallocator. There are no restrictions over the installed allocatorother than the ones imposed by the domain (for instance, the RawDomain allows the allocator to be called without the GIL held). Seethe section on allocator domains for moreinformation.

  • If called after Python has finish initializing (afterPy_InitializeFromConfig() has been called) the allocatormust wrap the existing allocator. Substituting the currentallocator for some other arbitrary one isnot supported.

Changed in version 3.12:All allocators must be thread-safe.

voidPyMem_SetupDebugHooks(void)

Setupdebug hooks in the Python memory allocatorsto detect memory errors.

Debug hooks on the Python memory allocators

WhenPython is built in debug mode, thePyMem_SetupDebugHooks() function is called at thePythonpreinitialization to setup debug hooks on Python memory allocatorsto detect memory errors.

ThePYTHONMALLOC environment variable can be used to install debughooks on a Python compiled in release mode (ex:PYTHONMALLOC=debug).

ThePyMem_SetupDebugHooks() function can be used to set debug hooksafter callingPyMem_SetAllocator().

These debug hooks fill dynamically allocated memory blocks with special,recognizable bit patterns. Newly allocated memory is filled with the byte0xCD (PYMEM_CLEANBYTE), freed memory is filled with the byte0xDD(PYMEM_DEADBYTE). Memory blocks are surrounded by “forbidden bytes”filled with the byte0xFD (PYMEM_FORBIDDENBYTE). Strings of these bytesare unlikely to be valid addresses, floats, or ASCII strings.

Runtime checks:

On error, the debug hooks use thetracemalloc module to get thetraceback where a memory block was allocated. The traceback is only displayediftracemalloc is tracing Python memory allocations and the memory blockwas traced.

LetS =sizeof(size_t).2*S bytes are added at each end of each blockofN bytes requested. The memory layout is like so, where p represents theaddress returned by a malloc-like or realloc-like function (p[i:j] meansthe slice of bytes from*(p+i) inclusive up to*(p+j) exclusive; notethat the treatment of negative indices differs from a Python slice):

p[-2*S:-S]

Number of bytes originally asked for. This is a size_t, big-endian (easierto read in a memory dump).

p[-S]

API identifier (ASCII character):

p[-S+1:0]

Copies of PYMEM_FORBIDDENBYTE. Used to catch under- writes and reads.

p[0:N]

The requested memory, filled with copies of PYMEM_CLEANBYTE, used to catchreference to uninitialized memory. When a realloc-like function is calledrequesting a larger memory block, the new excess bytes are also filled withPYMEM_CLEANBYTE. When a free-like function is called, these areoverwritten with PYMEM_DEADBYTE, to catch reference to freed memory. Whena realloc- like function is called requesting a smaller memory block, theexcess old bytes are also filled with PYMEM_DEADBYTE.

p[N:N+S]

Copies of PYMEM_FORBIDDENBYTE. Used to catch over- writes and reads.

p[N+S:N+2*S]

Only used if thePYMEM_DEBUG_SERIALNO macro is defined (not defined bydefault).

A serial number, incremented by 1 on each call to a malloc-like orrealloc-like function. Big-endiansize_t. If “bad memory” is detectedlater, the serial number gives an excellent way to set a breakpoint on thenext run, to capture the instant at which this block was passed out. Thestatic function bumpserialno() in obmalloc.c is the only place the serialnumber is incremented, and exists so you can set such a breakpoint easily.

A realloc-like or free-like function first checks that the PYMEM_FORBIDDENBYTEbytes at each end are intact. If they’ve been altered, diagnostic output iswritten to stderr, and the program is aborted via Py_FatalError(). The othermain failure mode is provoking a memory error when a program reads up one ofthe special bit patterns and tries to use it as an address. If you get in adebugger then and look at the object, you’re likely to see that it’s entirelyfilled with PYMEM_DEADBYTE (meaning freed memory is getting used) orPYMEM_CLEANBYTE (meaning uninitialized memory is getting used).

Changed in version 3.6:ThePyMem_SetupDebugHooks() function now also works on Pythoncompiled in release mode. On error, the debug hooks now usetracemalloc to get the traceback where a memory block was allocated.The debug hooks now also check if the GIL is held when functions ofPYMEM_DOMAIN_OBJ andPYMEM_DOMAIN_MEM domains arecalled.

Changed in version 3.8:Byte patterns0xCB (PYMEM_CLEANBYTE),0xDB (PYMEM_DEADBYTE)and0xFB (PYMEM_FORBIDDENBYTE) have been replaced with0xCD,0xDD and0xFD to use the same values than Windows CRT debugmalloc() andfree().

The pymalloc allocator

Python has apymalloc allocator optimized for small objects (smaller or equalto 512 bytes) with a short lifetime. It uses memory mappings called “arenas”with a fixed size of either 256 KiB on 32-bit platforms or 1 MiB on 64-bitplatforms. It falls back toPyMem_RawMalloc() andPyMem_RawRealloc() for allocations larger than 512 bytes.

pymalloc is thedefault allocator of thePYMEM_DOMAIN_MEM (ex:PyMem_Malloc()) andPYMEM_DOMAIN_OBJ (ex:PyObject_Malloc()) domains.

The arena allocator uses the following functions:

  • VirtualAlloc() andVirtualFree() on Windows,

  • mmap() andmunmap() if available,

  • malloc() andfree() otherwise.

This allocator is disabled if Python is configured with the--without-pymalloc option. It can also be disabled at runtime usingthePYTHONMALLOC environment variable (ex:PYTHONMALLOC=malloc).

Customize pymalloc Arena Allocator

Added in version 3.4.

typePyObjectArenaAllocator

Structure used to describe an arena allocator. The structure hasthree fields:

Field

Meaning

void*ctx

user context passed as first argument

void*alloc(void*ctx,size_tsize)

allocate an arena of size bytes

voidfree(void*ctx,void*ptr,size_tsize)

free an arena

voidPyObject_GetArenaAllocator(PyObjectArenaAllocator*allocator)

Get the arena allocator.

voidPyObject_SetArenaAllocator(PyObjectArenaAllocator*allocator)

Set the arena allocator.

The mimalloc allocator

Added in version 3.13.

Python supports the mimalloc allocator when the underlying platform support is available.mimalloc “is a general purpose allocator with excellent performance characteristics.Initially developed by Daan Leijen for the runtime systems of the Koka and Lean languages.”

tracemalloc C API

Added in version 3.7.

intPyTraceMalloc_Track(unsignedintdomain,uintptr_tptr,size_tsize)

Track an allocated memory block in thetracemalloc module.

Return0 on success, return-1 on error (failed to allocate memory tostore the trace). Return-2 if tracemalloc is disabled.

If memory block is already tracked, update the existing trace.

intPyTraceMalloc_Untrack(unsignedintdomain,uintptr_tptr)

Untrack an allocated memory block in thetracemalloc module.Do nothing if the block was not tracked.

Return-2 if tracemalloc is disabled, otherwise return0.

Examples

Here is the example from sectionOverview, rewritten so that theI/O buffer is allocated from the Python heap by using the first function set:

PyObject*res;char*buf=(char*)PyMem_Malloc(BUFSIZ);/* for I/O */if(buf==NULL)returnPyErr_NoMemory();/* ...Do some I/O operation involving buf... */res=PyBytes_FromString(buf);PyMem_Free(buf);/* allocated with PyMem_Malloc */returnres;

The same code using the type-oriented function set:

PyObject*res;char*buf=PyMem_New(char,BUFSIZ);/* for I/O */if(buf==NULL)returnPyErr_NoMemory();/* ...Do some I/O operation involving buf... */res=PyBytes_FromString(buf);PyMem_Del(buf);/* allocated with PyMem_New */returnres;

Note that in the two examples above, the buffer is always manipulated viafunctions belonging to the same set. Indeed, it is required to use the samememory API family for a given memory block, so that the risk of mixing differentallocators is reduced to a minimum. The following code sequence contains twoerrors, one of which is labeled asfatal because it mixes two differentallocators operating on different heaps.

char*buf1=PyMem_New(char,BUFSIZ);char*buf2=(char*)malloc(BUFSIZ);char*buf3=(char*)PyMem_Malloc(BUFSIZ);...PyMem_Del(buf3);/* Wrong -- should be PyMem_Free() */free(buf2);/* Right -- allocated via malloc() */free(buf1);/* Fatal -- should be PyMem_Del()  */

In addition to the functions aimed at handling raw memory blocks from the Pythonheap, objects in Python are allocated and released withPyObject_New,PyObject_NewVar andPyObject_Del().

These will be explained in the next chapter on defining and implementing newobject types in C.