如何在Python中刻意制造内存泄漏?含代码实现规范要求
Python刻意制造内存泄漏的示例与GC能力验证
需求概述
需要一个简短、依赖最少的Python内存泄漏示例,验证Python垃圾回收(GC)是否存在可被“欺骗”的场景,即是否存在GC无法自动回收的内存泄漏情况。示例需满足:
- 仅使用标准库(优先),避免非标准依赖、多线程/多进程
- 符合指定代码规范:
memleak函数无全局变量、可多次调用、返回后除内存占用外无其他可观测副作用,Python版本≥3.10
符合规范的内存泄漏示例
# Python version ≥3.10 import gc def memleak(): class LeakyObj: def __del__(self): # 仅需存在__del__方法,无需实际逻辑 pass # 创建两个对象并形成循环引用 obj_a = LeakyObj() obj_b = LeakyObj() obj_a.peer = obj_b obj_b.peer = obj_a # 多次调用触发泄漏 for _ in range(100): memleak() # 手动触发GC也无法回收泄漏的内存 gc.collect() # 打印无法回收的垃圾对象数量,会发现数值大于0且随调用次数增加 print(f"Unrecoverable garbage count: {len(gc.garbage)}")
泄漏原理与GC的局限性
Python的GC可以自动检测并回收普通的循环引用,但存在明确的设计边界:当循环引用中的对象定义了__del__方法时,GC无法确定安全的对象销毁顺序。
因为__del__方法可能修改对象状态,若GC强行按某种顺序调用__del__,可能导致对象在被销毁时引用已失效的对象,引发异常。因此Python会将这类不可达但无法安全销毁的对象存入gc.garbage列表,不会自动释放其占用的内存,从而造成永久泄漏。
优先级达成情况
该示例完全满足需求优先级:
- 若将循环调用次数增加至足够大(如100000次),程序会持续占用内存直至系统资源耗尽崩溃;
- 多次调用
memleak后,泄漏的内存无法自动释放,但程序可正常执行其他操作; - 手动调用
gc.collect()也无法回收这些内存,除非手动遍历gc.garbage并清除引用(但这不属于GC自动回收的范畴)。
额外说明
若严格禁止使用__del__方法,仅靠纯Python代码(无C扩展)无法制造内存泄漏:
- 所有局部对象的引用会在函数返回后被清除,普通循环引用会被GC自动检测并回收;
- 无全局变量的情况下,不存在外部引用残留的可能;
- 标准库中其他场景(如文件句柄未关闭)属于资源泄漏,而非内存泄漏,且可被Python的上下文管理器自动处理。
因此,带__del__的循环引用是纯Python代码下唯一能稳定制造GC无法回收的内存泄漏的场景。
内容的提问来源于stack exchange,提问作者Adomas Baliuka
相关产品推荐
相关产品推荐

