PyCapsule_New接受一个析构函数,当胶囊被销毁时调用这个函数:
PyObject* PyCapsule_New(void *pointer, const char *name, PyCapsule_Destructor destructor)
我试图使用这种机制将由C++代码创建的对象的所有权传递给Python。具体来说,析构函数只是调用对象的"delete“。
auto ptr = make_unique<ObjType>(arg);
PyObject * ret = PyCapsule_New(ptr.release(), nullptr, Destroyer);
void Destroyer(PyObject *capsule)
{
auto rawPtr = static_cast<ObjType*>(PyCapsule_GetPointer(capsule, nullptr));
delete rawPtr;
}
在我看来,这里似乎存在一个潜在的内存泄漏:如果PyCapsule_New失败,释放的原始指针就会变得悬空。我试图从Python文档中获得确认。但是,它只提到在失败时设置一个异常,并返回一个NULL。它没有提到所有权。
假定指针将处于悬空状态似乎是合理的,因为如果胶囊最初没有生成,就没有处理程序传递给析构函数。
但是,我不确定PyCapsule_New内部是否调用析构函数,特别是:
如果突出显示的部分永远不会发生,在我看来,上面的代码必须重写为
auto ptr = make_unique<ObjType>(arg);
PyObject * ret = PyCapsule_New(ptr.get(), nullptr, Destroyer);
if (ret != nullptr)
ptr.release();
有人能帮我确认一下是否是这样吗?
发布于 2017-03-20 14:36:31
如建议的那样,改变评论以回答。
简短的回答:不,当PyCapsule_New失败时,它不会调用驱逐舰。
参见https://github.com/python/cpython/blob/master/Objects/capsule.c#L44中的实现
PyObject *
PyCapsule_New(void *pointer, const char *name, PyCapsule_Destructor destructor)
{
PyCapsule *capsule;
if (!pointer) {
PyErr_SetString(PyExc_ValueError, "PyCapsule_New called with null pointer");
return NULL;
}
capsule = PyObject_NEW(PyCapsule, &PyCapsule_Type);
if (capsule == NULL) {
return NULL;
}
capsule->pointer = pointer;
capsule->name = name;
capsule->context = NULL;
capsule->destructor = destructor;
return (PyObject *)capsule;
}
因此,第一个实现确实包含潜在的内存泄漏。只有在PyCapsule_New成功时才应该调用"release()“。
https://stackoverflow.com/questions/42818669
复制相似问题