我有一些类似于下面的代码。那个代码泄露了,我不知道为什么。泄漏的是在 C 代码中简单创建 Python 类的实例。我用来检查泄漏的函数是
create_n_times
,它在下面定义并且只是创建新的 Python 实例并在循环中取消引用它们。
这本身不是 MWE,而是示例的一部分。为了更容易理解,代码所做的是:
set_ip_settings_type
将其注册到 C 扩展中。create_n_times
被调用,该函数创建和销毁 Python 数据类的 n
实例。有人能帮忙吗?
在 Python 中:
import c_api
@dataclass
class IpSettings:
ip: str
port: int
dhcp: bool
c_api.set_ip_settings_type(IpSettings)
c_api.generate_n_times(100000)
在 C++ 中,我将以下代码编译成一个名为
c_api
的 Python 扩展(它是该库定义的一部分):
#include <Python.h>
// ... Other functions including a "PyInit" function
extern "C" {
PyObject* ip_settings_type = NULL;
PyObject* set_ip_settings_type(PyObject* tp)
{
Py_XDECREF(ip_settings_type);
Py_INCREF(tp);
ip_settings_type = tp;
return Py_None;
}
PyObject* create_n_times(PyObject* n)
{
long n_ = PyLong_AsLong(n);
for (int i = 0; i < n_ ++i)
{
PyObject* factory_object = ip_settings_type;
PyObject* args = PyTuple_New(3);
PyTuple_SetItem(args, 0, PyUnicode_FromString("123.123.123.123"));
PyTuple_SetItem(args, 1, PyLong_FromUnsignedLong(1231));
PyTuple_SetItem(args, 2, Py_False);
PyObject* obj = PyObject_CallObject(factory_object, args);
Py_DECREF(obj);
}
return Py_None;
}
}
PyTuple_SetItem
窃取了对所提供对象的引用,但是 Py_False
是单个对象。当 args 元组被销毁时,Py_False 的引用计数会被破坏。
使用
PyBool_FromLong(0)
创建对 Py_False
的新引用,就像对 PyTuple_SetItem
的其他两个调用一样。 (参见 docs.python.org/3/c-api/bool.html)