TL; DR
您需要del
因为vector
不是一个Python类。
再回应
有很多的因素,使得它不可能蟒蛇垃圾收集器收集对象:
vector
实例没有因为他们的类的引用计数属性/ struct不包括PyObject_HEAD
。这是一个C(C++)类,为什么呢?
Python对象使用PyObject_GC_New
使其实例知道垃圾收集器和PyObject_GC_Del
(或PyObject_GC_UnTrack
)删除。但vector
使用new
创建(在堆上),因此垃圾回收器不涉及在所有,因此您需要一个明确的del
(我认为delete
也应该工作,但我没有检查)删除。
这可以在源代码中被视为良好(I使用ipythons %%cython
这样的实施例中是可再现的):
%%cython --cplus
from libcpp.vector cimport vector
def simple_test(double x):
v = new vector[double]()
try:
v.push_back(1.0)
v.push_back(x)
from math import pi
v.push_back(pi)
return v.size()
finally:
del v
给出了以下的.cpp
文件(的极端)缩短代码(通常这文件位于.ipython/cython
文件夹在你的home目录):
/* "_cython_magic_9df9dbf5f4981f282eb46337245f3bb9.pyx":9
* 3
* """
* v = new vector[double]() # <<<<<<<<<<<<<<
* try:
* v.push_back(1.0)
*/
try {
__pyx_t_1 = new std::vector<double>();
} catch(...) {
[...]
}
__pyx_v_v = __pyx_t_1;
/* "_cython_magic_9df9dbf5f4981f282eb46337245f3bb9.pyx":17
* return v.size()
* finally:
* del v # <<<<<<<<<<<<<<
*/
[...]
{
delete __pyx_v_v;
}
所以没有del v
有禾这不是delete
声明,你会(可能)在你的代码中有内存泄漏。
实际测试
%%cython --cplus
from libcpp.vector cimport vector
def simple_test(double x):
v = new vector[double]()
for _ in range(20000000):
v.push_back(x)
return v.size()
# NO "del"!!!
import psutil
for _ in range(10):
simple_test(10)
print(psutil.virtual_memory().percent)
它打印:
47.5
49.4
51.2
53.1
55.1
57.0
58.9
60.8
62.8
65.0
66.9
68.9
70.6
72.5
74.5
76.4
78.4
80.3
82.2
83.6
所以,至少在我的电脑上,这导致不断增加的内存使用情况,而一个与del
不会:
%%cython --cplus
from libcpp.vector cimport vector
def simple_test(double x):
v = new vector[double]()
try:
for _ in range(20000000):
v.push_back(x)
return v.size()
finally:
del v # this one has a del statement!!!
import psutil
for _ in range(20):
simple_test(10)
print(psutil.virtual_memory().percent)
结果:
47.4
47.4
47.4
47.4
47.4
47.4
47.4
47.4
47.2
47.2
47.2
47.2
47.2
47.2
47.2
47.2
47.2
47.2
47.2
47.3
垃圾收集器会自动清理它。 – Barmar
@Barmar我不这么认为。除了任何理论上的考虑因素(因为它是一个C对象而不是Python对象,pythons gc如何知道何时以及如何收集它)只是运行该代码会在我的计算机上产生内存泄漏。 – MSeifert