【问题标题】:Does this code create a memory leak in python?此代码是否会在 python 中造成内存泄漏?
【发布时间】:2018-02-28 17:56:18
【问题描述】:

考虑以下代码来说明建议:

import mod

f1s = ["A1", "B1", "C1"]
f2s = ["A2", "B2", "C2"]

for f1, f2 in zip(f1s,f2s):

    # Creating an object
    acumulator = mod.AcumulatorObject()

    # Using object
    acumulator.append(f1)
    acumulator.append(f2)

    # Output of object
    acumulator.print()

所以,我在for 开头使用了一个类的实例来执行一个操作。对于for 中的每个元组,我需要执行相同的操作,但是我不能使用相同的对象,因为它会添加最后一次迭代的效果。因此,在每次迭代开始时,我都会创建一个新实例。

我的问题是这样做是否会造成内存泄漏?对于创建的每个对象,我必须执行什么操作? (可能删除它?或者通过将新对象分配给它被清除的相同名称?)

【问题讨论】:

  • 据我了解,一旦引用计数达到零,对象就会在下一个 GC 周期中被垃圾回收。所以答案是否定的,因为变量acumulator 将不再指向在上一次循环迭代中创建的对象,GC 将在下一次遍历中将其擦除,无需显式执行。
  • 这不会对 Python 造成任何问题。 Python 是一种内存管理语言,在这里,引用计数将负责回收对象。
  • @juanpa.arrivillaga 尽管您应该关注文件指针等系统资源——特别是在不使用 GC 引用计数的实现上——尤其是 Pypy、Jython 和 IronPython。
  • @PauloScardine 是的,确实如此。我想说人们也应该担心 CPython 中的这些事情。

标签: python python-3.x


【解决方案1】:

tl,博士;没有

Python 的引用实现使用引用计数来进行垃圾收集。还有其他实现使用不同的 GC 策略,这会影响调用 __del__ 方法的精确时间,这在 PyPy、Jython 或 IronPython 中可能可靠或不及时。这些差异并不重要,除非您处理文件指针和其他昂贵的系统资源等资源。

在 cPython 中,当引用计数为零时,GC 将清除对象。例如,当您在 for 循环中执行 acumulator = mod.AcumulatorObject() 时,新对象会在下一次迭代中替换旧对象 - 由于没有其他变量引用旧对象,它将在下一次 GC 传递中被垃圾收集。参考实现 cPython 会在超出范围时自动释放资源,而其他实现则为 YMMV。

这就是为什么许多人评论说内存泄漏在 Python 中不是问题。

您可以使用cg 模块完全控制cPython 的垃圾收集器。默认设置非常保守,在以 Python 为生的 10 年里,我从未手动触发 GC 循环 - but I've seen a situation where delaying it helped performance:

是的,我以前玩过 sys.setcheckinterval。我将它更改为 1000(从默认值 100),但它没有做任何可测量的差异。禁用垃圾收集有帮助 - 谢谢。这是迄今为止最大的加速 - 节省了大约 20%(整个运行 171 分钟,下降到 135 分钟) - 我不确定误差线是什么,但它必须是统计上显着的增加。

只需遵循最佳做法,例如使用 with 或(try/finally 块)包装系统资源,您应该没有问题。

【讨论】:

    猜你喜欢
    • 2017-12-05
    • 1970-01-01
    • 1970-01-01
    • 2020-01-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-04
    • 2016-02-04
    相关资源
    最近更新 更多