::-- hoxide [2005-03-24 15:19:39]

1. 概述

简述

  • 本文详细分析了python的垃圾收集机制, 顺带简要介绍内存管理机制. 力求让读者能对python的内存管理方面建立一个清晰的图景.

1.1. 相关文件

include/object.h
include/objimpl.h
objects/object.c
objects/weakrefobject.c
modules/gcmodule.c

1.2. 基本垃圾收集 --- 引用计数

  • Python的内存管理基础是引用计数机制. 引用计数机制是建立在对象的引用计数值等于指向他的引用个数之和这个范式成立的基础上的. 由于Python是单根继承的类型系统, 所有类继承自Object, 因此只要分析Object的引用计数即可. 下面粗略得看一下源代码. 看文件'include/object.h', 他定义了object对象的结构, 是python对象的定义框架.

   1 /* PyObject_HEAD defines the initial segment of every PyObject. */
   2 #define PyObject_HEAD                   \
   3         _PyObject_HEAD_EXTRA            \
   4         int ob_refcnt;                  \
   5         struct _typeobject *ob_type;
   6 
   7 #define PyObject_HEAD_INIT(type)        \
   8         _PyObject_EXTRA_INIT            \
   9         1, type,

   1 /* Nothing is actually declared to be a PyObject, but every pointer to
   2  * a Python object can be cast to a PyObject*.  This is inheritance built
   3  * by hand.  Similarly every pointer to a variable-size Python object can,
   4  * in addition, be cast to PyVarObject*.
   5  */
   6 typedef struct _object {
   7         PyObject_HEAD
   8 } PyObject;

object类型只是简单得包含了PyObject_HEAD域, 而PyObject_HEAD中定义的ob_refcnt就是存放引用计数的. 宏PyObject_HEAD_INIT是用来初始化对象头的,可用看到初始时引用计数为1.

   1 #define Py_INCREF(op) (                         \
   2         _Py_INC_REFTOTAL  _Py_REF_DEBUG_COMMA   \
   3         (op)->ob_refcnt++)
   4 
   5 #define Py_DECREF(op)                                   \
   6         if (_Py_DEC_REFTOTAL  _Py_REF_DEBUG_COMMA       \
   7             --(op)->ob_refcnt != 0)                     \
   8                 _Py_CHECK_REFCNT(op)                    \
   9         else                                            \
  10                 _Py_Dealloc((PyObject *)(op))

这段宏定义了增加和减少引用计数的代码, 可用看到引用计数等于零时将会销毁对象. 这就构成了引用计数的整体构架.

从Python源码和API使用说明中都可以看到, 程序员通常需要用额外的代码手动维护引用计数范式的成立.

1.3. GC模块 --- 收集环形结构

1.4. 弱引用 --- 解决 __del__ 中的引用悖论