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 C API文档中获得确认。但是,它只提到失败时设置了异常,并返回NULL。它没有谈论所有权。
假设指针悬空是合理的,因为如果首先没有生成包,那么就没有处理程序可以传递给析构函数。
但是,我不确定PyCapsule_New是否在内部调用析构函数,具体来说:
如果突出显示的部分永远不会发生,我觉得上面的代码必须重写为
auto ptr = make_unique<ObjType>(arg);
PyObject * ret = PyCapsule_New(ptr.get(), nullptr, Destroyer);
if (ret != nullptr)
ptr.release();
有人可以帮助确认是否属实?
答案 0 :(得分:0)
根据建议更改评论以回答。
简短回答:不,当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()”。