首先,看下面这个案例
l1 = ['a', 'b']
l2 = ['x', 'y']
l1.append(l2)
print(l1)
print(id(l2), id(l1[2]))
l2.append(l1)
print(l2)
print(id(l1), id(l2[2]))
# 这两个列表存在一种相互引用的关系,就叫做循环引用
----------------------------------------------------------------
# 运行结果:
['a', 'b', ['x', 'y']]
2230756681088 2230756681088
['x', 'y', ['a', 'b', [...]]]
2230756998272 2230756998272
del l1
del l2
现在已经把这两个列表的直接引用全部解除了,但是它们身上的引用计数并没有变成0,它们身上只有它们相互的间接引用,再也没办法取到这两个列表了,所以这两个列表这时候就变成了一个永远回收不了的垃圾,永远占着这两块内存空间,这就叫内存泄漏
其次,了解栈区和堆区
name = '小圆子'
# 见下图,栈区专门用来存放变量名,堆区专门用来存放变量值
最后,分析最上面的案例
紧接最上面的案例,见下面两张图,下方堆区的两块内存就泄露了,这时候python就提供了一个叫标记清除的解决方案:
标记清除会在你python程序内存空间不够用的时候,将整个程序暂停下来,扫描栈区,把通过栈区所有能引用到的值(不管是通过栈区直接引用还是间接引用到的),都标记为存活状态,一旦发现有通过栈区引用不到的值,都标记为死亡状态,死亡状态的值会直接被清理掉,就算它身上的引用计数不为0,只要访问不到它了,标记清除就会把它标记成垃圾,然后回收掉