CPython 的内存管理分三层:对象分配器(pymalloc,针对小对象做内存池化)、引用计数为主的对象生命周期管理、分代垃圾回收为辅以解决循环引用。
引用计数:每个 PyObject 头部存 ob_refcnt,引用增加 +1、减少 -1,归零立即释放并递归递减其成员。优点是回收即时、确定性;缺点是无法处理循环引用,且计数维护有开销。
分代 GC 补漏:针对容器对象(list、dict、自定义类实例等可能产生循环的对象),GC 维护三个代(0/1/2)。新对象进第 0 代,每代有分配/回收差值阈值,超过触发该代及更年轻一代的回收。回收时用标记-清除变体:把容器对象间引用图做遍历,减去内部互相引用,剩余不可达集合即为循环垃圾。存活对象晋升到老年代,基于"越老越不容易死"的假设减少扫描频率。
内存池:小于 512 字节的对象走 pymalloc 的 arena/pool/block 三级结构,避免频繁 malloc 和碎片。
易错点与追问:循环引用对象即使不可达,引用计数也不归零(需靠 GC);含 __del__ 的旧式循环引用曾无法回收;__slots__、弱引用(weakref)是打破循环引用的常用手段;sys.getrefcount 可观察计数。