Python中结构体的CTypes内存泄漏问题

3

Python的ctypes是否存在已知的内存泄漏?我正在编写一个类似下面代码段的Python脚本,使用ctypes,某种原因导致内存泄漏。此示例中的"while True"是为了测试调用函数引起的泄漏。它在Windows上使用Python 2.5.4运行:

import ctypes
def hi():
    class c1(ctypes.Structure):
            _fields_=[('f1',ctypes.c_uint8)]
    class c2(ctypes.Structure):
            _fields_=[('g1',c1*2)]

while True:
    test=hi()

这个泄漏可以使用ProcessExplorer进行测试--当它循环时,Python会占用越来越多的内存。似乎需要有两个结构子类,其中一个类具有另一个类的“倍数”(使用*运算符),但我不确定条件是否比这更基本。即使在循环中添加del test,它仍然会泄漏内存。

你有什么想法是什么导致了这个问题吗?

编辑:因为有人建议它可能尚未进行垃圾收集,所以这里有一个经过编辑的版本,它确实进行了垃圾收集,但仍然似乎存在内存泄漏:

import gc
import ctypes
def hi():
    class c1(ctypes.Structure):
            _fields_=[('f1',ctypes.c_uint8)]
    class c2(ctypes.Structure):
            _fields_=[('g1',c1*2)]

while True:
    test=hi()
    test2=gc.collect()

它泄漏了多少?每个创建的 c1 是一个字节吗?有一个计数器,每调用 hi() 大约 50,000 次就会打印一次,这样你就知道了。 - agf
在ProcessExplorer中,“工作集”内存每秒稳定增加约20-30 KB,而“私有字节”也会偶尔追上它。大约12分钟后,我在解释器中运行的第二个片段已经超过了59 MB的内存,并且还在不断增长。我该如何在代码中放置一个计数器,告诉你正在占用多少内存?还有其他人可以证实我的说法吗? - user553702
最简单的方法是在顶部添加 from itertools import count,然后将 while True: 更改为 for c in count():,然后在循环中添加 if not c % 50000: print c。然后,如果 print 太频繁或太少以至于无用,可以增加或减少那个 50000 - agf
我已经添加了一个错误跟踪器案例;这是交叉引用:http://bugs.python.org/issue12998 - user553702
从那个案例的回复中可以看出,这并不是一种泄漏。你真的不应该尝试使用进程监视器作为泄漏检测工具。 - David Heffernan
显示剩余2条评论
2个回答

2

这并不是内存泄漏,仅仅意味着垃圾回收器还没有运行。即使垃圾回收器确实运行了,很有可能存在某种类型的内存池。

ProcessExplorer并不是一个好的调试工具,特别是对于内存方面。


即使我在开头添加了“import gc”,并在循环内部添加了“test2 = gc.collect()”,它所占用的内存仍然不断增长。你所说的“内存池”是什么意思?难道内存不应该在某个时候被释放吗? - user553702
内存池意味着在 Python 中设置了一个区域来保存空闲内存。这是一种优化技术。它只看起来像内存正在被使用。 - Chris Eberle

1
脚本本身并不泄漏。使用gc.set_debug(gc.DEBUG_LEAK)运行显示创建的结构类型是可收集的,并且在每个循环迭代中gc.garbage保持为空,因此没有无法收集的对象。在Linux系统上使用time运行脚本也不会显示内存消耗的稳定增加。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接