zoukankan      html  css  js  c++  java
  • Python垃圾回收机制:gc模块(zz)

     在Python中,为了解决内存泄露问题,采用了对象引用计数,并基于引用计数实现自动垃圾回

        由于Python 有了自动垃圾回收功能,就造成了不少初学者误认为不必再受内存泄漏的骚扰了。但如果仔细查看一下Python文档对 __del__() 函数的描述,就知道这种好日子里也是有阴云的。下面摘抄一点文档内容如下:

    Some common situations that may prevent the reference count of an object from going to zero include: circular references between objects (e.g., a doubly-linked list or a tree data structure with parent and child pointers); a reference to the object on the stack frame of a function that caught an exception (the traceback stored in sys.exc_traceback keeps the stack frame alive); or a reference to the object on the stack frame that raised an unhandled exception in interactive mode (the traceback stored in sys.last_traceback keeps the stack frame alive).

      可见, __del__() 函数的对象间的循环引用是导致内存泄漏的主凶。但没有__del__()函数的对象间的循环引用是可以被垃圾回收器回收掉的。

        如何知道一个对象是否内存泄露掉了呢?

        可以通过Python的扩展模块gc来查看不能回收掉的对象的详细信息。

    例1:没有出现内存泄露的

    import gc
    import sys
    
    class CGcLeak(object):
        def __init__(self):
            self._text='#'*10
    
        def __del__(self):
            pass
    
    
    def make_circle_ref():
        _gcleak=CGcLeak()
        
        print("_gcleak ref count0:{}".format(sys.getrefcount(_gcleak)))
        del _gcleak
    
        try:
            print("_gcleak ref count:{}".format(sys.getrefcount(_gcleak)))
        except UnboundLocalError:
            print("_gcleak is invalid!")
    
    def test_gcleak():
        gc.enable()
    
        print("begin leak test...")
        make_circle_ref()
    
        print
        "
    begin collect..."
        _unreachable = gc.collect()
        print("unreachable object num:{}".format(_unreachable))
        print("garbage object num:{}".format(len(gc.garbage)))
    
    
    if __name__ == "__main__":
        test_gcleak()

    结果

    C:Python35python.exe C:/wcf/django/ftest/ftest.py
    begin leak test...
    _gcleak ref count0:2
    _gcleak is invalid!
    unreachable object num:0
    garbage object num:0
    
    Process finished with exit code 0

    例2:对自己的循环引用造成内存泄露

    import gc
    import sys
    
    class CGcLeak(object):
        def __init__(self):
            self._text='#'*10
    
        def __del__(self):
            pass
    
    
    def make_circle_ref():
        _gcleak=CGcLeak()
        _gcleak._self = _gcleak
        print("_gcleak ref count0:{}".format(sys.getrefcount(_gcleak)))
        del _gcleak
    
        try:
            print("_gcleak ref count:{}".format(sys.getrefcount(_gcleak)))
        except UnboundLocalError:
            print("_gcleak is invalid!")
    
    def test_gcleak():
        gc.enable()
    
        print("begin leak test...")
        make_circle_ref()
    
        print
        "
    begin collect..."
        _unreachable = gc.collect()
        print("unreachable object num:{}".format(_unreachable))
        print("garbage object num:{}".format(len(gc.garbage)))
    
    
    if __name__ == "__main__":
        test_gcleak()

    结果是:

    C:Python35python.exe C:/wcf/django/ftest/ftest.py
    begin leak test...
    _gcleak ref count0:3
    _gcleak is invalid!
    unreachable object num:2
    garbage object num:0
    
    Process finished with exit code 0

    例3:多个对象间的循环引用造成内存泄露 

    import gc
    import sys
    
    class CGcLeakA(object):
        def __init__(self):
            self._text='#'*10
    
        def __del__(self):
            pass
    
    class CGcLeakB(object):
        def __init__(self):
            self._text='$'*10
    
        def __del__(self):
            pass
    
    
    def make_circle_ref():
        _a=CGcLeakA()
        _b = CGcLeakB()
        _a.s=_b
        _b.s=_a
    
        print("ref count0:_a is {},_b is {}".format(sys.getrefcount(_a),sys.getrefcount(_a)))
        del _a
        del _b
    
    
        try:
            print("ref count:_a is {}".format(sys.getrefcount(_a)))
        except UnboundLocalError:
            print("_a is invalid!")
    
    def test_gcleak():
        gc.enable()
    
        print("begin leak test...")
        make_circle_ref()
    
        print
        "
    begin collect..."
        _unreachable = gc.collect()
        print("unreachable object num:{}".format(_unreachable))
        print("garbage object num:{}".format(len(gc.garbage)))
    
    
    if __name__ == "__main__":
        test_gcleak()

    运行结果:

    import gc
    import sys
    
    class CGcLeakA(object):
        def __init__(self):
            self._text='#'*10
    
        def __del__(self):
            pass
    
    class CGcLeakB(object):
        def __init__(self):
            self._text='$'*10
    
        def __del__(self):
            pass
    
    
    def make_circle_ref():
        _a=CGcLeakA()
        _b = CGcLeakB()
        _a.s=_b
        _b.s=_a
    
        print("ref count0:_a is {},_b is {}".format(sys.getrefcount(_a),sys.getrefcount(_a)))
        del _a
        del _b
    
    
        try:
            print("ref count:_a is {}".format(sys.getrefcount(_a)))
        except UnboundLocalError:
            print("_a is invalid!")
    
    def test_gcleak():
        gc.enable()
    
        print("begin leak test...")
        make_circle_ref()
    
        print
        "
    begin collect..."
        _unreachable = gc.collect()
        print("unreachable object num:{}".format(_unreachable))
        print("garbage object num:{}".format(len(gc.garbage)))
    
    
    if __name__ == "__main__":
        test_gcleak()

    转自:

    http://www.cnblogs.com/kaituorensheng/p/4449457.html

  • 相关阅读:
    LeetCode5654. 盒子中小球的最大数量
    LeetCode40. 组合总和 II
    LeetCode39. 组合总和
    LeetCode17. 电话号码的字母组合
    Leetcode216. 组合总和 III
    eclipse相关使用
    matlab符号的含义
    matlab矩阵相关的笔记
    vi编辑器
    Linux 环境变量
  • 原文地址:https://www.cnblogs.com/aomi/p/7569545.html
Copyright © 2011-2022 走看看