在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:没有出现内存泄露的

  1. import gc
  2. import sys
  3.  
  4. class CGcLeak(object):
  5. def __init__(self):
  6. self._text='#'*10
  7.  
  8. def __del__(self):
  9. pass
  10.  
  11. def make_circle_ref():
  12. _gcleak=CGcLeak()
  13.  
  14. print("_gcleak ref count0:{}".format(sys.getrefcount(_gcleak)))
  15. del _gcleak
  16.  
  17. try:
  18. print("_gcleak ref count:{}".format(sys.getrefcount(_gcleak)))
  19. except UnboundLocalError:
  20. print("_gcleak is invalid!")
  21.  
  22. def test_gcleak():
  23. gc.enable()
  24.  
  25. print("begin leak test...")
  26. make_circle_ref()
  27.  
  28. print
  29. "\nbegin collect..."
  30. _unreachable = gc.collect()
  31. print("unreachable object num:{}".format(_unreachable))
  32. print("garbage object num:{}".format(len(gc.garbage)))
  33.  
  34. if __name__ == "__main__":
  35. test_gcleak()

结果

  1. C:\Python35\python.exe C:/wcf/django/ftest/ftest.py
  2. begin leak test...
  3. _gcleak ref count0:2
  4. _gcleak is invalid!
  5. unreachable object num:0
  6. garbage object num:0
  7.  
  8. Process finished with exit code 0

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

  1. import gc
  2. import sys
  3.  
  4. class CGcLeak(object):
  5. def __init__(self):
  6. self._text='#'*10
  7.  
  8. def __del__(self):
  9. pass
  10.  
  11. def make_circle_ref():
  12. _gcleak=CGcLeak()
  13. _gcleak._self = _gcleak
  14. print("_gcleak ref count0:{}".format(sys.getrefcount(_gcleak)))
  15. del _gcleak
  16.  
  17. try:
  18. print("_gcleak ref count:{}".format(sys.getrefcount(_gcleak)))
  19. except UnboundLocalError:
  20. print("_gcleak is invalid!")
  21.  
  22. def test_gcleak():
  23. gc.enable()
  24.  
  25. print("begin leak test...")
  26. make_circle_ref()
  27.  
  28. print
  29. "\nbegin collect..."
  30. _unreachable = gc.collect()
  31. print("unreachable object num:{}".format(_unreachable))
  32. print("garbage object num:{}".format(len(gc.garbage)))
  33.  
  34. if __name__ == "__main__":
  35. test_gcleak()

结果是:

  1. C:\Python35\python.exe C:/wcf/django/ftest/ftest.py
  2. begin leak test...
  3. _gcleak ref count0:3
  4. _gcleak is invalid!
  5. unreachable object num:2
  6. garbage object num:0
  7.  
  8. Process finished with exit code 0

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

  1. import gc
  2. import sys
  3.  
  4. class CGcLeakA(object):
  5. def __init__(self):
  6. self._text='#'*10
  7.  
  8. def __del__(self):
  9. pass
  10.  
  11. class CGcLeakB(object):
  12. def __init__(self):
  13. self._text='$'*10
  14.  
  15. def __del__(self):
  16. pass
  17.  
  18. def make_circle_ref():
  19. _a=CGcLeakA()
  20. _b = CGcLeakB()
  21. _a.s=_b
  22. _b.s=_a
  23.  
  24. print("ref count0:_a is {},_b is {}".format(sys.getrefcount(_a),sys.getrefcount(_a)))
  25. del _a
  26. del _b
  27.  
  28. try:
  29. print("ref count:_a is {}".format(sys.getrefcount(_a)))
  30. except UnboundLocalError:
  31. print("_a is invalid!")
  32.  
  33. def test_gcleak():
  34. gc.enable()
  35.  
  36. print("begin leak test...")
  37. make_circle_ref()
  38.  
  39. print
  40. "\nbegin collect..."
  41. _unreachable = gc.collect()
  42. print("unreachable object num:{}".format(_unreachable))
  43. print("garbage object num:{}".format(len(gc.garbage)))
  44.  
  45. if __name__ == "__main__":
  46. test_gcleak()

运行结果:

  1. import gc
  2. import sys
  3.  
  4. class CGcLeakA(object):
  5. def __init__(self):
  6. self._text='#'*10
  7.  
  8. def __del__(self):
  9. pass
  10.  
  11. class CGcLeakB(object):
  12. def __init__(self):
  13. self._text='$'*10
  14.  
  15. def __del__(self):
  16. pass
  17.  
  18. def make_circle_ref():
  19. _a=CGcLeakA()
  20. _b = CGcLeakB()
  21. _a.s=_b
  22. _b.s=_a
  23.  
  24. print("ref count0:_a is {},_b is {}".format(sys.getrefcount(_a),sys.getrefcount(_a)))
  25. del _a
  26. del _b
  27.  
  28. try:
  29. print("ref count:_a is {}".format(sys.getrefcount(_a)))
  30. except UnboundLocalError:
  31. print("_a is invalid!")
  32.  
  33. def test_gcleak():
  34. gc.enable()
  35.  
  36. print("begin leak test...")
  37. make_circle_ref()
  38.  
  39. print
  40. "\nbegin collect..."
  41. _unreachable = gc.collect()
  42. print("unreachable object num:{}".format(_unreachable))
  43. print("garbage object num:{}".format(len(gc.garbage)))
  44.  
  45. if __name__ == "__main__":
  46. test_gcleak()

转自:

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

Python垃圾回收机制:gc模块(zz)的更多相关文章

  1. Python垃圾回收机制:gc模块

    在Python中,为了解决内存泄露问题,采用了对象引用计数,并基于引用计数实现自动垃圾回收. 由于Python 有了自动垃圾回收功能,就造成了不少初学者误认为不必再受内存泄漏的骚扰了.但如果仔细查看一 ...

  2. 浅析Python垃圾回收机制!

    Python垃圾回收机制 目录 Python垃圾回收机制 1. 内存泄露 2. Python什么时候启动垃圾回收机制? 2.1 计数引用 2.2 循环引用 问题:引用计数是0是启动垃圾回收的充要条件吗 ...

  3. 简述Python垃圾回收机制和常量池的验证

    目录 通过代码验证python解释器内部使用了常量池 Python的引入 变量的引入 为什么要有变量 定义变量 常量引入 常量池引入 Python解释器 Python变量存储机制 Python垃圾回收 ...

  4. 垃圾回收机制GC

    垃圾回收机制GC 我们已经知道,name = 'leethon'这一赋值变量的操作,是将变量与数据值相绑定. 而数据值是存储到内存中的,有时变量会重新赋值即绑定其他数据值,而使得原本的数据值无法通过变 ...

  5. 垃圾回收机制GC知识再总结兼谈如何用好GC

    一.为什么需要GC 应用程序对资源操作,通常简单分为以下几个步骤: 1.为对应的资源分配内存 2.初始化内存 3.使用资源 4.清理资源 5.释放内存 应用程序对资源(内存使用)管理的方式,常见的一般 ...

  6. 垃圾回收机制GC知识再总结兼谈如何用好GC(转)

    作者:Jeff Wong 出处:http://jeffwongishandsome.cnblogs.com/ 本文版权归作者和博客园共有,欢迎围观转载.转载时请您务必在文章明显位置给出原文链接,谢谢您 ...

  7. python垃圾回收机制与小整数池

    python垃圾回收机制 当引用计数为0时,python会删除这个值. 引用计数 x = 10 y = x del x print(y) 10 引用计数+1,引用计数+1,引用计数-1,此时引用计数为 ...

  8. python垃圾回收机制:引用计数 VS js垃圾回收机制:标记清除

    js垃圾回收机制:标记清除 Js具有自动垃圾回收机制.垃圾收集器会按照固定的时间间隔周期性的执行. JS中最常见的垃圾回收方式是标记清除. 工作原理 当变量进入环境时,将这个变量标记为"进入 ...

  9. 垃圾回收机制GC知识再总结兼谈如何用好GC(其他信息: 内存不足)

    来源 图像操作,易内存泄露,边界像素 一.为什么需要GC 应用程序对资源操作,通常简单分为以下几个步骤: 1.为对应的资源分配内存 2.初始化内存 3.使用资源 4.清理资源 5.释放内存 应用程序对 ...

随机推荐

  1. linux下easy_install的安装与使用详解

    Python中的easy_install工具用起来非常好用,它的作用类似于Php中的pear,或者Ruby中的gem,或者Perl中的cpan. 1.easy_install安装 如果想使用easy_ ...

  2. 【转】C++ const用法 尽可能使用const

    http://www.cnblogs.com/xudong-bupt/p/3509567.html C++ const 允许指定一个语义约束,编译器会强制实施这个约束,允许程序员告诉编译器某值是保持不 ...

  3. awk,rsync,重启,maxdepth一层目录,登录,开机自启动

    有100个日志文件,每个文件大约1G,每条日志都以 “H:i:s” 的时间格式开头,如: 05:02:04 xxx yyy zzz 因为是日志文件,所以肯定以时间为顺序的,现在可以确定的是,在某个文件 ...

  4. can be found for element 'tx:annotation-driven'

    错误描述: ERROR [ContainerBackgroundProcessor[StandardEngine[Catalina]]] (ContextLoader.java:308) - Cont ...

  5. vector 基础2

    size  :返回有效元素个数 max_size  :返回 vector 支持的最大元素个数 resize  :改变有效元素的个数 capacity  :返回当前可使用的最大元素内存块数(即存储容量) ...

  6. Codeforces Round #351 (VK Cup 2016 Round 3, Div. 2 Edition) B

    B. Problems for Round time limit per test 2 seconds memory limit per test 256 megabytes input standa ...

  7. [poj 2274]后缀数组+最长公共子串

    题目链接:http://poj.org/problem?id=2774 后缀数组真的太强大了,原本dp是O(nm)的复杂度,在这里只需要O(n+m). 做法:将两个串中间夹一个未出现过的字符接起来,然 ...

  8. Codeforces Round #478 C. Valhalla Siege

    C. Valhalla Siege time limit per test 2 seconds memory limit per test 256 megabytes input standard i ...

  9. POJ 3179 Corral the Cows

    Corral the Cows Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 1352   Accepted: 565 De ...

  10. HDU 多校对抗赛第二场 1010 Swaps and Inversions

    Swaps and Inversions Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Oth ...