确定Python中是否发生内存泄漏

时间:2014-11-12 18:12:33

标签: python garbage-collection cpython

我的理解是,在以下情况下,Python中的内存泄漏(至少是> Cpython 2.0)只能

  1. 包含一个或多个对象的循环引用图 使用__del__方法
  2. 扩展C / C ++或其他内部执行和泄漏内存的本机代码模块
  3. 当然,我们需要区分 实际内存泄漏 (一个程序,其中对象永远不能通过垃圾收集器回收或定期引用计数)一个程序,它只是耗尽了内存,因为它不断分配永不消亡的对象 - (但仍然触手可及) - 通常是因为它们的参考图连接了一些全局变量。

    为了区分这两种情况(即实际的内存泄漏与只保持分配永不过时的可收集对象的程序),我们可以简单地连续调用gc.collect()并检查返回值是否为0

    换句话说,如果以下程序永远不会失败AssertionError(由于线程2中的断言)我们有效证明 否内存泄漏 (如上所述)?

    Thread 1:
       ... run actual application code ...
    
    Thread 2:
      while True:
        num = gc.collect()
        assert num == 0
        time.sleep(WAIT_TIME)
    

    要清楚,我只是问这个程序是否会证明上面的案例(1)和(2)所定义的实际内存泄漏没有发生 - 我意识到这不会证明该程序将会由于分配太多,永远不会耗尽内存。

1 个答案:

答案 0 :(得分:0)

即使没有内存泄漏,此程序也很可能抛出AssertionError。它会在GC收集任何内容时执行此操作(gc.collect()在此情况下返回非零值)。 OTOH,gc.collect()不会收集您所指的"实际的内存泄漏,"所以他们 不会在gc.collect()返回值中报告。

简而言之,不,这个程序根本不会正确检测内存泄漏。如果你想要抓住案例(1),你可以定期检查以确保gc.garbage为空,但这不会遇到案例(2),因为GC只涉及管理扩展模块' s内存,如果模块询问(即使这样,只在模块正确跟踪其拥有的引用的范围内)。对于一般情况,您需要类似Valgrind的内容。