Memory management C-API:分配;PyTypeObject扩展名“;

Memory management C-API:分配;PyTypeObject扩展名“;,memory-management,python-c-api,pycxx,Memory Management,Python C Api,Pycxx,我在PyCXX中发现了一些可能有缺陷的代码 它确实是一个bug吗?如果是的话,正确的修复方法是什么 PythonClassInstance foo{}; PyObject* tmp = subtype->tp_alloc(subtype,0); // !!! memcpy sizeof(PyObject) bytes starting from location tmp into location (void*)foo 问题是: struct PythonClassInstance

我在PyCXX中发现了一些可能有缺陷的代码

它确实是一个bug吗?如果是的话,正确的修复方法是什么

PythonClassInstance foo{};

PyObject* tmp = subtype->tp_alloc(subtype,0);

// !!! memcpy sizeof(PyObject) bytes starting from location tmp into location (void*)foo
问题是:

struct PythonClassInstance
{
    PyObject_HEAD
    ExtObjBase* m_pycxx_object;
}
:
{
    :
    table->tp_new = extension_object_new; // PyTypeObject
    :
}
:
static PyObject* extension_object_new( 
                 PyTypeObject* subtype, PyObject* args, PyObject* kwds )
{
    PythonClassInstance* o = reinterpret_cast<PythonClassInstance *>
                                       ( subtype->tp_alloc(subtype,0) );
    if( ! o )
        return nullptr;

    o->m_pycxx_object = nullptr;

    PyObject* self = reinterpret_cast<PyObject* >( o );

    return self;
}
但我想现在也许我需要释放tmp,我不认为我应该像这样直接使用内存。我觉得这可能会危及Python内置的内存管理/垃圾收集机制

另一个选项是,我可能可以说服tp_alloc分配4个额外字节(或者现在是8个字节;足够一个指针)绕过1而不是0

文件中说,第二个参数是“Py_ssize_t nitems”,并且:

如果类型的tp_itemsize为非零,则对象的ob_size字段 应初始化为nitems和分配内存的长度 块应为tp_basicsize+nitemstp_itemsize,四舍五入为a sizeof(void)的倍数;否则,不使用nitems,并且 砌块的长度应为tp_basicsize

所以看起来我应该设置:

table->tp_itemsize = sizeof(void*);
:
PyObject* tmp = subtype->tp_alloc(subtype,1);
编辑:刚刚尝试了这个,它导致了崩溃

但随后,文件中继续说:

不要使用此函数进行任何其他实例初始化,而不是 甚至分配额外的内存;这应该由tp_new完成

现在我不确定这段代码是属于tp_new还是tp_init

相关的:

代码是正确的

只要扩展对象的PyTypeObject被正确初始化,它就会工作

基类
tp_alloc
接收
子类型
,因此它应该通过检查
tp_basicsize
成员知道要分配多少内存

这是一个常见的Python C/API模式,如图所示。

实际上这是一个(次要/无害的)

所以我想把这个答案转换成一个评论,这没有任何意义,我不能授予绿色完成勾号,所以我评论。所以我必须漫无目的地说,才能使它合格。布莱尔