面试题答案
一键面试常见导致内存泄漏的场景
- 循环引用:对象之间相互引用,导致垃圾回收器无法回收它们。例如两个类的实例互相引用对方。
class A:
def __init__(self):
self.b = None
class B:
def __init__(self):
self.a = None
a = A()
b = B()
a.b = b
b.a = a
- 全局变量:在模块中定义的全局变量,如果不断向其添加新对象,而没有适当的清理机制,可能导致内存泄漏。
global_list = []
def add_to_global():
global global_list
while True:
global_list.append([1] * 10000)
- 文件或资源未关闭:打开文件、数据库连接等资源后,如果没有正确关闭,可能会导致内存泄漏。
def memory_leak_file():
while True:
f = open('test.txt', 'w')
f.write('test')
# 未执行f.close() ,文件对象一直占用内存
使用 memory_profiler 检测内存泄漏
- 安装:使用
pip install memory_profiler
安装该工具。 - 使用装饰器检测函数:
from memory_profiler import profile
@profile
def test_memory_leak():
data = []
for _ in range(10000):
data.append([1] * 1000)
return data
运行包含上述代码的脚本,memory_profiler
会输出函数执行过程中的内存使用情况,帮助分析是否存在内存泄漏。
- 逐行分析:如果要逐行分析代码的内存使用情况,可以使用
mprof run
命令。例如,将上述test_memory_leak
函数保存到test.py
文件中,执行mprof run test.py
,然后使用mprof plot
生成内存使用随时间变化的图表,更直观地查看哪部分代码导致内存增长异常。