Python Src – How PyMem_GetAllocator() and PyMem_SetAllocator() work

_PyMem_RawMalloc is calling ‘malloc’ to allocate memory and return pointer
so _PyMem_RawMalloc is equal to ‘malloc’

1
2
3
4
5
6
7
8
9
10
11
static void *
_PyMem_RawMalloc(void *ctx, size_t size)
{
    /* PyMem_RawMalloc(0) means malloc(1). Some systems would return NULL
       for malloc(0), which would be treated as an error. Some platforms would
       return a pointer with no memory behind it, which would break pymalloc.
       To solve these problems, allocate an extra byte. */
    if (size == 0)
        size = 1;
    return malloc(size);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
typedef struct {
    /* user context passed as the first argument to the 4 functions */
    void *ctx;
 
    /* allocate a memory block */
    void* (*malloc) (void *ctx, size_t size);
 
    /* allocate a memory block initialized by zeros */
    void* (*calloc) (void *ctx, size_t nelem, size_t elsize);
 
    /* allocate or resize a memory block */
    void* (*realloc) (void *ctx, void *ptr, size_t new_size);
 
    /* release a memory block */
    void (*free) (void *ctx, void *ptr);
} PyMemAllocatorEx;
 
#define PYRAW_FUNCS _PyMem_RawMalloc, _PyMem_RawCalloc, _PyMem_RawRealloc, _PyMem_RawFree // this means
//*ctx = NULL and (*malloc) = _PyMem_RawMalloc = malloc function in c
 
        PyMemAllocatorEx alloc = {NULL, PYRAW_FUNCS}; 
 
// alloc will be assigned to _PyMem_Raw, _PyMem, _PyObject
// for PyMem_GetAllocator, it will get alloc by domain name and pick up one of allocator _PyMem_Raw, _PyMem, _PyObject
        PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &alloc);
        PyMem_SetAllocator(PYMEM_DOMAIN_MEM, &alloc);
        PyMem_SetAllocator(PYMEM_DOMAIN_OBJ, &alloc);
void
PyMem_SetAllocator(PyMemAllocatorDomain domain, PyMemAllocatorEx *allocator)
{
    switch(domain)
    {
    case PYMEM_DOMAIN_RAW: _PyMem_Raw = *allocator; break;
    case PYMEM_DOMAIN_MEM: _PyMem = *allocator; break;
    case PYMEM_DOMAIN_OBJ: _PyObject = *allocator; break;
    /* ignore unknown domain */
    }
}

There are 3 Domains that are PYMEM_DOMAIN_RAW, PYMEM_DOMAIN_MEM, PYMEM_DOMAIN_OBJ

alloc will be assigned to _PyMem_Raw, _PyMem, _PyObject based on 3 Domains.
for PyMem_GetAllocator, it will get alloc by domain name and pick up one of allocator _PyMem_Raw, _PyMem, _PyObject