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.
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.
New in version 3.4.
- void*
PyMem_RawMalloc
(size_t n)¶ Allocatesn bytes and returns a pointer of type
void*
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_t nelem, size_t elsize)¶ Allocatesnelem elements each whose size in bytes iselsize and returnsa pointer of type
void*
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.New in version 3.5.
- void*
PyMem_RawRealloc
(void *p, size_t n)¶ Resizes the memory block pointed to byp ton bytes. The contents willbe unchanged to the minimum of the old and the new sizes.
Ifp is
NULL
, 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 is
NULL
, 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.
- void
PyMem_RawFree
(void *p)¶ Frees the memory block pointed to byp, which must have been returned by aprevious call to
PyMem_RawMalloc()
,PyMem_RawRealloc()
orPyMem_RawCalloc()
. Otherwise, or ifPyMem_RawFree(p)
has beencalled before, undefined behavior occurs.Ifp is
NULL
, 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_t n)¶ Allocatesn bytes and returns a pointer of type
void*
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_t nelem, size_t elsize)¶ Allocatesnelem elements each whose size in bytes iselsize and returnsa pointer of type
void*
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.New in version 3.5.
- void*
PyMem_Realloc
(void *p, size_t n)¶ Resizes the memory block pointed to byp ton bytes. The contents will beunchanged to the minimum of the old and the new sizes.
Ifp is
NULL
, 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 is
NULL
, 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.
- void
PyMem_Free
(void *p)¶ Frees the memory block pointed to byp, which must have been returned by aprevious call to
PyMem_Malloc()
,PyMem_Realloc()
orPyMem_Calloc()
. Otherwise, or ifPyMem_Free(p)
has been calledbefore, undefined behavior occurs.Ifp is
NULL
, no operation is performed.
The following type-oriented macros are provided for convenience. Note thatTYPE refers to any C type.
- TYPE*
PyMem_New
(TYPE, size_t n)¶ Same as
PyMem_Malloc()
, but allocates(n*sizeof(TYPE))
bytes ofmemory. Returns a pointer cast toTYPE*
. The memory will not havebeen initialized in any way.
- TYPE*
PyMem_Resize
(void *p, TYPE, size_t n)¶ Same as
PyMem_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.
- void
PyMem_Del
(void *p)¶ Same as
PyMem_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.
Thedefault object allocator uses thepymalloc memory allocator.
Warning
TheGIL must be held when using thesefunctions.
- void*
PyObject_Malloc
(size_t n)¶ Allocatesn bytes and returns a pointer of type
void*
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_t nelem, size_t elsize)¶ Allocatesnelem elements each whose size in bytes iselsize and returnsa pointer of type
void*
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.New in version 3.5.
- void*
PyObject_Realloc
(void *p, size_t n)¶ Resizes the memory block pointed to byp ton bytes. The contents will beunchanged to the minimum of the old and the new sizes.
Ifp is
NULL
, 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 is
NULL
, 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.
- void
PyObject_Free
(void *p)¶ Frees the memory block pointed to byp, which must have been returned by aprevious call to
PyObject_Malloc()
,PyObject_Realloc()
orPyObject_Calloc()
. Otherwise, or ifPyObject_Free(p)
has been calledbefore, undefined behavior occurs.Ifp is
NULL
, no operation is performed.
Default Memory Allocators¶
Default memory allocators:
Configuration | Name | PyMem_RawMalloc | PyMem_Malloc | PyObject_Malloc |
---|---|---|---|---|
Release build |
|
|
|
|
Debug build |
|
|
|
|
Release build, without pymalloc |
|
|
|
|
Debug build, without pymalloc |
|
|
|
|
Legend:
Name: value for
PYTHONMALLOC
environment variablemalloc
: system allocators from the standard C library, C functions:malloc()
,calloc()
,realloc()
andfree()
pymalloc
:pymalloc memory allocator“+ debug”: with debug hooks installed by
PyMem_SetupDebugHooks()
Customize Memory Allocators¶
New in version 3.4.
PyMemAllocatorEx
¶Structure used to describe a memory block allocator. The structure hasfour 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:The
PyMemAllocator
structure was renamed toPyMemAllocatorEx
and a newcalloc
field was added.
PyMemAllocatorDomain
¶Enum used to identify an allocator domain. Domains:
PYMEM_DOMAIN_RAW
¶Functions:
PYMEM_DOMAIN_MEM
¶Functions:
PYMEM_DOMAIN_OBJ
¶Functions:
- void
PyMem_GetAllocator
(PyMemAllocatorDomain domain,PyMemAllocatorEx *allocator)¶ Get the memory block allocator of the specified domain.
- void
PyMem_SetAllocator
(PyMemAllocatorDomain domain,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 the
PYMEM_DOMAIN_RAW
domain, the allocator must bethread-safe: theGIL is not held when theallocator is called.If the new allocator is not a hook (does not call the previous allocator),the
PyMem_SetupDebugHooks()
function must be called to reinstall thedebug hooks on top on the new allocator.
- void
PyMem_SetupDebugHooks
(void)¶ Setup hooks to detect bugs in the Python memory allocator functions.
Newly allocated memory is filled with the byte
0xCD
(CLEANBYTE
),freed memory is filled with the byte0xDD
(DEADBYTE
). Memory blocksare surrounded by “forbidden bytes” (FORBIDDENBYTE
: byte0xFD
).Runtime checks:
Detect API violations, ex:
PyObject_Free()
called on a bufferallocated byPyMem_Malloc()
Detect write before the start of the buffer (buffer underflow)
Detect write after the end of the buffer (buffer overflow)
Check that theGIL is held whenallocator functions of
PYMEM_DOMAIN_OBJ
(ex:PyObject_Malloc()
) andPYMEM_DOMAIN_MEM
(ex:PyMem_Malloc()
) domains are called
On error, the debug hooks use the
tracemalloc
module to get thetraceback where a memory block was allocated. The traceback is onlydisplayed iftracemalloc
is tracing Python memory allocations and thememory block was traced.These hooks areinstalled by default ifPython is compiled in debugmode. The
PYTHONMALLOC
environment variable can be used to installdebug hooks on a Python compiled in release mode.Changed in version 3.6:This function now also works on Python compiled in release mode.On error, the debug hooks now use
tracemalloc
to get the tracebackwhere a memory block was allocated. The debug hooks now also checkif the GIL is held when functions ofPYMEM_DOMAIN_OBJ
andPYMEM_DOMAIN_MEM
domains are called.Changed in version 3.8:Byte patterns
0xCB
(CLEANBYTE
),0xDB
(DEADBYTE
) and0xFB
(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 256 KiB. 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.
Customize pymalloc Arena Allocator¶
New in version 3.4.
PyObjectArenaAllocator
¶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
- void
PyObject_GetArenaAllocator
(PyObjectArenaAllocator *allocator)¶ Get the arena allocator.
- void
PyObject_SetArenaAllocator
(PyObjectArenaAllocator *allocator)¶ Set the arena allocator.
tracemalloc C API¶
New in version 3.7.
- int
PyTraceMalloc_Track
(unsigned int domain, uintptr_t ptr, size_t size)¶ Track an allocated memory block in the
tracemalloc
module.Return
0
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.
- int
PyTraceMalloc_Untrack
(unsigned int domain, uintptr_t ptr)¶ Untrack an allocated memory block in the
tracemalloc
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.