大师兄的Python源码学习笔记(四十六): Python的内存管理机制(一)

大师兄的Python源码学习笔记(四十五): Python的多线程机制(七)

  • Python所有的内存管理机制都有两套实现,由编译符号PYMALLOC_DEBUG控制:
  • 当该符号被定义时,使用的是debug模式下的内存管理机制,这套机制在正常的内存管理动作之外,还会记录许多关于内存的信息,以方便Python在开发时进行调试。
  • 当该符号未被定义时,进行正常的内存管理动作。
  • 我们的焦点放在非debug模式下的内存管理机制上。

一、内存管理架构

  • Python中的内存管理机制被抽象成一种层次似的结果:


1. 第0层
  • 第0层是操作系统提供的内存管理接口,比如C提供的malloc和free接口。
  • 这一层由操作系统提供,Python不干涉这一层的行为。
  • 从这一层往上全部由Python实现并维护。
2. 第1层
  • 第1层基于第0层操作系统的管理接口包装而成。
  • 为了最广泛的可移植性,这一层为Python提供一层统一的raw memory的管理接口。
Include\pymem.h

PyAPI_FUNC(void *) PyMem_RawMalloc(size_t size);
PyAPI_FUNC(void *) PyMem_RawCalloc(size_t nelem, size_t elsize);
PyAPI_FUNC(void *) PyMem_RawRealloc(void *ptr, size_t new_size);
PyAPI_FUNC(void) PyMem_RawFree(void *ptr);
Objects\obmalloc.c

void *
PyMem_RawMalloc(size_t size)
{
    /*
     * Limit ourselves to PY_SSIZE_T_MAX bytes to prevent security holes.
     * Most python internals blindly use a signed Py_ssize_t to track
     * things without checking for overflows or negatives.
     * As size_t is unsigned, checking for size < 0 is not required.
     */
    if (size > (size_t)PY_SSIZE_T_MAX)
        return NULL;
    return _PyMem_Raw.malloc(_PyMem_Raw.ctx, size);
}

void *
PyMem_RawCalloc(size_t nelem, size_t elsize)
{
    /* see PyMem_RawMalloc() */
    if (elsize != 0 && nelem > (size_t)PY_SSIZE_T_MAX / elsize)
        return NULL;
    return _PyMem_Raw.calloc(_PyMem_Raw.ctx, nelem, elsize);
}

void*
PyMem_RawRealloc(void *ptr, size_t new_size)
{
    /* see PyMem_RawMalloc() */
    if (new_size > (size_t)PY_SSIZE_T_MAX)
        return NULL;
    return _PyMem_Raw.realloc(_PyMem_Raw.ctx, ptr, new_size);
}

void PyMem_RawFree(void *ptr)
{
    _PyMem_Raw.free(_PyMem_Raw.ctx, ptr);
}
  • 可以看到,在第1层提供了类似C中malloc,calloc,realloc,free的语义。
  • 此外,在第1层中,还提供了面向Python中类型的内存分配器:
Include\pymem.h

/*
 * Type-oriented memory interface
 * ==============================
 *
 * Allocate memory for n objects of the given type.  Returns a new pointer
 * or NULL if the request was too large or memory allocation failed.  Use
 * these macros rather than doing the multiplication yourself so that proper
 * overflow checking is always done.
 */

#define PyMem_New(type, n) \
  ( ((size_t)(n) > PY_SSIZE_T_MAX / sizeof(type)) ? NULL :      \
        ( (type *) PyMem_Malloc((n) * sizeof(type)) ) )
#define PyMem_NEW(type, n) \
  ( ((size_t)(n) > PY_SSIZE_T_MAX / sizeof(type)) ? NULL :      \
        ( (type *) PyMem_MALLOC((n) * sizeof(type)) ) )

/*
 * The value of (p) is always clobbered by this macro regardless of success.
 * The caller MUST check if (p) is NULL afterwards and deal with the memory
 * error if so.  This means the original value of (p) MUST be saved for the
 * caller's memory error handler to not lose track of it.
 */
#define PyMem_Resize(p, type, n) \
  ( (p) = ((size_t)(n) > PY_SSIZE_T_MAX / sizeof(type)) ? NULL :        \
        (type *) PyMem_Realloc((p), (n) * sizeof(type)) )
#define PyMem_RESIZE(p, type, n) \
  ( (p) = ((size_t)(n) > PY_SSIZE_T_MAX / sizeof(type)) ? NULL :        \
        (type *) PyMem_REALLOC((p), (n) * sizeof(type)) )

/* PyMem{Del,DEL} are left over from ancient days, and shouldn't be used
 * anymore.  They're just confusing aliases for PyMem_{Free,FREE} now.
 */
#define PyMem_Del               PyMem_Free
#define PyMem_DEL               PyMem_FREE
  • 比如在PyMem_New中,只需要提供类型和数量,就会自动侦测所需的内存空间大小。
3. 第2层
  • 为了简化开发,Python在比第1层更高的抽象层次上提供了第2层内存管理接口。
  • 在这一层,是一组以PyObje_为前缀的函数族,主要提供了创建Python对象的接口。
  • 这一套函数族又称作Pymalloc机制。
  • 第2层是真正在Python中发挥巨大作用的一层内存管理机制,同时也是GC的藏身之处,后面我们会深入剖析这层。
4. 第3层
  • 第2层的管理机制上,Python又对一些常用对象,比如int对象,string对象等构建了更高抽象层次的内存管理策略。
  • 对于第3层的内存管理策略,主要就是对象缓冲池机制,这个在大师兄的Python源码学习笔记(四): 字符串对象中已经介绍过了。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容