Python 默认内存处理机制为GC(垃圾回收)


内存泄漏

指由于疏忽或错误造成程序未能释放已经不再使用的内存的情况。

  • 内存泄漏并非指内存在物理上的消失,而是应用程序分配某段内存后, 由于设计错误, 失去了对该段内存的控制, 因而造成了内存的浪费, 导致程序运行速度减慢甚至系统崩溃等严重后果。有 __del__() 函数的对象间的循环引用是导致内存泄漏的主凶。
  • 不使用一个对象时使用: del object 来删除一个对象的引用计数就可以有效防止内存泄漏问题。
    通过 Python 扩展模块 gc 来查看不能回收的对象的详细信息, 也可以通过 sys.getrefcount(obj) 来获取对象的引用计数, 并根据返回值是否为 0 来判断是否内存泄漏。

内存管理机制

一. 引用计数
通过引用计数来保持对内存中的变量跟踪Python内部记录中所有在使用对象各有多少个引用。
Python中有个内部跟踪变量叫做引用计数器, 每个变量有多少个引用, 简称引用计数。当对象被创建时就创建了一个引用计数。当某个对象的引用计数为0时, 对象就不在需要, 就列入了垃圾回收队列。
二. 垃圾回收

  • __引用计数__:每个对象中都有ob-refcnt来做引用计数。当一个对象被引用, ob-refcnt就会增加, 当引用的对象删除, 那么ob-refcnt就会减少, 当ob-refcnt为零, 就会释放该对象的内存空间。
  • __标记清除__:解决循环引用的问题。先按需分配, 等到没有空闲内存的时候, 从寄存器和程序栈上的引用出发, 遍历所有对象和引用把所有能访问的打标记, 最后将没有标记的对象释放掉。
  • __分代技术__:提高效率, 提高垃圾回收的效率, 按照存活时间, 分成不同的集合。将内存块按照其存活时间划分为不同的集合。每个集合就称为一个“代”, 垃圾回收的频率随代的存活时间增大而减小。Python默认定义分代对象集合, 引用数越大, 对象的存活时间越长。

三. 内存池机制

  • 在Python中, 大多数申请的都是小块的内存, 会执行大量的malloc和free操作。Python引入了一个内存池机制, 用于管理对小块内存的申请和释放, 即Pymalloc机制。它将不用的内存放到内存池而不是返回给操作系统。
  • 当申请的内存小于256字节时, PyObject_Malloc会在内存池中申请内存; 当申请的内存大于256字节时, PyObject_Malloc的行为将蜕化为malloc的行为。当然, 通过修改Python源代码, 我们可以改变这个默认值, 从而改变Python的默认内存管理行为。
  • 对于Python对象, 如整数, 浮点数和List, 都有其独立的私有内存池, 对象间不共享他们的内存池。也就是说如果你分配又释放了大量的整数, 用于缓存这些整数的内存就不能再分配给浮点数。