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