python垃圾回收机制 以及内存泄露_Python垃圾回收机制及gc模块详解:内存泄露的例子...

标记清理是用来解决循环引用的。分代回收针对所有的新创建即进入0代的对象和进入1、2代的对象。。这样就解释了python“引用计数为主。标记清理+分代回收为辅”的垃圾回收原理,因为循环引用毕竟是少数情况。

# 没有循环引用的情况,随着del、函数退出等触发条件,立即删除所占用内存

import gc

import sys

gc.set_debug(gc.DEBUG_STATS|gc.DEBUG_COLLECTABLE|gc.DEBUG_UNCOLLECTABLE|gc.DEBUG_SAVEALL|gc.DEBUG_LEAK)

a=[]

b=[]

print(hex(id(a)))

print(hex(id(b)))

a.append(b)

print('a refcount:',sys.getrefcount(a)) # 2print('b refcount:',sys.getrefcount(b)) # 3del a # 这里已经删除了,内存也被回收了,所以在gc进行垃圾回收的时候,不需要处理,毕竟gc是根据阈值设置触发执行的,没有立即删除那么快

del b # 这里已经删除了,内存也被回收了,所以在gc进行垃圾回收的时候,不需要处理

print(gc.collect()) #0

#放在解释器里执行:

>>> a=[]>>> b=[]>>>print(hex(id(a)))0x102918788

>>>print(hex(id(b)))0x1029187c8

>>>a.append(b)>>> print('a refcount:',sys.getrefcount(a)) # 2a refcount:2

>>> print('b refcount:',sys.getrefcount(b)) # 3b refcount:3

>>>... del a # 这里已经删除了,内存也被回收了,所以在gc进行垃圾回收的时候,不需要处理>>>del b # 这里已经删除了,内存也被回收了,所以在gc进行垃圾回收的时候,不需要处理>>> print(gc.collect()) # 0gc: collecting generation2...

gc: objectsin each generation: 4 0 4338gc: objectsin permanent generation: 0gc: done,0.0009s elapsed0 -----没有任何对象被回收>>>

# 下面的示例是存在循环引用的情况,所以del删除的时候,只是删除了对象的引用,对象没有被删除,所以在gc进行垃圾回收的时候,所用内存经过标记清理和分代回收动作被回收掉

a=[]

b=[]

print(hex(id(a)))

print(hex(id(b)))

a.append(b)

b.append(a)

del a

del b

print(gc.collect())

# 放到python3.7解释器里执行>>> a=[]>>> b=[]>>>print(hex(id(a)))0x102828888

>>>print(hex(id(b)))0x102828848

>>>a.append(b)>>>b.append(a)>>>del a>>>del b>>>print(gc.collect())

gc: collecting generation2...

gc: objectsin each generation: 6 0 4336gc: objectsin permanent generation: 0gc: collectablegc: collectablegc: done,2 unreachable, 0 uncollectable, 0.0010s elapsed 2 0---表示存在2个不可达对象,0个不可以回收的对象2 ---表示被回收了2个不可达对象>>>

# 下面这段代码在python3.7中执行不存在内存泄露;但是在python2.7环境中存在内存泄露classA:

def __del__(self):

passclassB:

def __del__(self):

pass

a=A()

b=B()

print(hex(id(a)))

print(hex(id(a.__dict__)))

a.b=b

b.a=a

del a

del b

print(gc.collect())

print(gc.garbage)

# pyhton3.7环境下执行>>> classA:

... def __del__(self):

... pass

...>>>...classB:

... def __del__(self):

... pass

...>>>

>>> a=A()>>> b=B()>>>print(hex(id(a)))0x10cfbfba8

>>>print(hex(id(a.__dict__)))0x10ce64f78

>>> a.b=b>>> b.a=a>>>del a>>>del b>>>... print(gc.collect())

gc: collecting generation2...

gc: objectsin each generation: 683 3813 0gc: objectsin permanent generation: 0gc: collectablegc: collectablegc: collectablegc: collectablegc: done,4 unreachable, 0 uncollectable, 0.0008s elapsed 4 0 ---存在4个不可达但是不存在不可以回收的对象,即4个不可达对象都可以回收4 ---回收了4个不可达的对象>>>print(gc.garbage)

[<__main__.a object at>, <__main__.b object at>, {'b': <__main__.b object at>}, {'a': <__main__.a object at>}]>>>

# python2.7环境下执行>>> classA:

... def __del__(self):

... pass

...

gc: collecting generation0...

gc: objectsin each generation: 658 3204 0gc: done,0.0002s elapsed.>>>

>>> classB:

... def __del__(self):

... pass

...>>> a=A()>>> b=B()>>>print(hex(id(a)))0x10239a2d8

>>>print(hex(id(a.__dict__)))0x10239b050

>>> a.b=b>>> b.a=a>>>del a>>>del b>>>... print(gc.collect())

gc: collecting generation2...

gc: objectsin each generation: 16 3552 0gc: uncollectablegc: uncollectablegc: uncollectablegc: uncollectablegc: done,4 unreachable, 4 uncollectable, 0.0008s elapsed. 4 4---存在4个不可达又不可以回收的对象4 ---回收了4个不可达对象>>>print(gc.garbage)

[<__main__.a instance at>, <__main__.b instance at>, {'b': <__main__.b instance at>}, {'a': <__main__.a instance at>}]>>>

>>>

这篇文章:https://python3-cookbook.readthedocs.io/zh_CN/latest/c08/p23_managing_memory_in_cyclic_data_structures.html举例的内存泄露的情况,也只有在python2.x中存在,python3.x貌似做了优化,并没有内存泄露:

如果循环引用的对象自己还定义了自己的 __del__() 方法,那么会让情况变得更糟糕。 假设你像下面这样给Node定义自己的 __del__() 方法:

# Class just to illustrate when deletion occursclassData:

def __del__(self):

print('Data.__del__')

# Nodeclassinvolving a cycleclassNode:

def __init__(self):

self.data=Data()

self.parent=None

self.children=[]

def add_child(self, child):

self.children.append(child)

child.parent=self

# NEVER DEFINE LIKE THIS.

# Only here to illustrate pathological behavior

def __del__(self):

del self.data

In [3]: a=Node()

In [4]: a.add_child(Node())

In [5]: del a

In [6]: import gc

In [7]: gc.collect()

Out[7]: 56In [8]: gc.garbage

Out[8]:

[<__main__.node instance at>,<__main__.data instance at>,<__main__.node instance at>,<__main__.data instance at>]

参考:

https://blog.csdn.net/yueguanghaidao/article/details/11274737

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值